or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

bulk-data.mdconfig-utils.mdindex.mdlive-streaming.mdmarket-sector.mdscreening.mdsearch-lookup.mdticker-data.md

market-sector.mddocs/

0

# Market and Sector Analysis

1

2

Market status information, sector performance data, and industry-level analysis for broader market intelligence. These capabilities provide macroeconomic context and sector-specific insights for investment research and market analysis.

3

4

## Capabilities

5

6

### Market Status and Summary

7

8

Access comprehensive market status information including trading hours, market state, and summary data across exchanges.

9

10

```python { .api }

11

class Market:

12

def __init__(self, market: str, session=None, timeout: int = 30):

13

"""

14

Create a Market object for accessing market-level data.

15

16

Parameters:

17

- market: str, market identifier (e.g., 'US', 'NYSE', 'NASDAQ')

18

- session: requests.Session, optional session for HTTP requests

19

- timeout: int, request timeout in seconds

20

"""

21

22

# Properties

23

status: dict # Market status information including trading hours and state

24

summary: dict # Market summary data organized by exchange

25

```

26

27

#### Market Status Information

28

29

The `status` property provides detailed market timing and operational information:

30

31

```python

32

# Market status structure

33

{

34

'market': 'US',

35

'timezone': 'America/New_York',

36

'current_time': '2024-01-15 14:30:00',

37

'market_state': 'REGULAR', # REGULAR, PRE, POST, CLOSED

38

'next_open': '2024-01-16 09:30:00',

39

'next_close': '2024-01-15 16:00:00',

40

'is_open': True,

41

'session_info': {

42

'regular_market_start': '09:30:00',

43

'regular_market_end': '16:00:00',

44

'pre_market_start': '04:00:00',

45

'post_market_end': '20:00:00'

46

}

47

}

48

```

49

50

#### Market Summary Data

51

52

The `summary` property provides aggregated market data by exchange:

53

54

```python

55

# Market summary structure

56

{

57

'NYSE': {

58

'advancing_issues': 1205,

59

'declining_issues': 892,

60

'unchanged_issues': 67,

61

'total_volume': 2847362100,

62

'advance_decline_ratio': 1.35

63

},

64

'NASDAQ': {

65

'advancing_issues': 1834,

66

'declining_issues': 1456,

67

'unchanged_issues': 123,

68

'total_volume': 3967234800,

69

'advance_decline_ratio': 1.26

70

}

71

}

72

```

73

74

#### Usage Examples

75

76

```python

77

import yfinance as yf

78

79

# US market analysis

80

us_market = yf.Market('US')

81

82

# Check if market is open

83

market_status = us_market.status

84

is_trading = market_status['is_open']

85

current_state = market_status['market_state']

86

87

print(f"Market is {'open' if is_trading else 'closed'}")

88

print(f"Current market state: {current_state}")

89

90

# Market breadth analysis

91

market_summary = us_market.summary

92

for exchange, data in market_summary.items():

93

advancing = data.get('advancing_issues', 0)

94

declining = data.get('declining_issues', 0)

95

ratio = data.get('advance_decline_ratio', 0)

96

97

print(f"{exchange}: {advancing} up, {declining} down (A/D: {ratio:.2f})")

98

```

99

100

### Sector-Level Analysis

101

102

Access sector-specific data including top ETFs, mutual funds, and constituent industries.

103

104

```python { .api }

105

class Sector:

106

def __init__(self, key: str, session=None):

107

"""

108

Create a Sector object for accessing sector-level data.

109

110

Parameters:

111

- key: str, sector key identifier (e.g., 'technology', 'healthcare', 'finance')

112

- session: requests.Session, optional session for HTTP requests

113

"""

114

115

# Properties

116

top_etfs: Dict[str, str] # Top ETFs in sector {symbol: name}

117

top_mutual_funds: Dict[str, str] # Top mutual funds {symbol: name}

118

industries: pd.DataFrame # Industries within the sector with performance data

119

```

120

121

#### Sector Properties Details

122

123

**Top ETFs**: Dictionary mapping ETF symbols to names for the sector

124

```python

125

{

126

'XLK': 'Technology Select Sector SPDR Fund',

127

'VGT': 'Vanguard Information Technology ETF',

128

'IYW': 'iShares U.S. Technology ETF',

129

'FTEC': 'Fidelity MSCI Information Technology Index ETF'

130

}

131

```

132

133

**Top Mutual Funds**: Dictionary mapping mutual fund symbols to names

134

```python

135

{

136

'FXNAX': 'Fidelity U.S. Sustainability Index Fund',

137

'VITAX': 'Vanguard Information Technology Index Fund',

138

'TRBCX': 'T. Rowe Price Blue Chip Growth Fund'

139

}

140

```

141

142

**Industries DataFrame**: Contains detailed industry breakdown within the sector

143

- Index: Industry names

144

- Columns: Performance metrics, market cap data, constituent counts

145

146

#### Usage Examples

147

148

```python

149

# Technology sector analysis

150

tech_sector = yf.Sector('technology')

151

152

# Get top investment vehicles

153

top_tech_etfs = tech_sector.top_etfs

154

top_tech_funds = tech_sector.top_mutual_funds

155

156

print("Top Technology ETFs:")

157

for symbol, name in top_tech_etfs.items():

158

print(f" {symbol}: {name}")

159

160

# Analyze sector industries

161

tech_industries = tech_sector.industries

162

print("\nTechnology Sector Industries:")

163

print(tech_industries)

164

165

# Industry performance comparison

166

if not tech_industries.empty:

167

# Assuming industries DataFrame has performance columns

168

best_performing = tech_industries.nlargest(3, 'performance')

169

print(f"\nBest performing tech industries:")

170

print(best_performing)

171

```

172

173

### Industry-Level Analysis

174

175

Access detailed industry-specific data including top performing companies and growth metrics.

176

177

```python { .api }

178

class Industry:

179

def __init__(self, key: str, session=None):

180

"""

181

Create an Industry object for accessing industry-level data.

182

183

Parameters:

184

- key: str, industry key identifier (e.g., 'software', 'semiconductors', 'biotechnology')

185

- session: requests.Session, optional session for HTTP requests

186

"""

187

188

# Properties

189

sector_key: str # Parent sector key

190

sector_name: str # Parent sector display name

191

top_performing_companies: pd.DataFrame # Top performing companies in industry

192

top_growth_companies: pd.DataFrame # Companies with highest growth rates

193

```

194

195

#### Industry Properties Details

196

197

**Parent Sector Information**:

198

- `sector_key`: Machine-readable sector identifier

199

- `sector_name`: Human-readable sector name

200

201

**Top Performing Companies DataFrame**:

202

- Columns: symbol, name, price, change, change_percent, market_cap, volume

203

- Sorted by performance metrics (typically price change or returns)

204

205

**Top Growth Companies DataFrame**:

206

- Columns: symbol, name, revenue_growth, earnings_growth, projected_growth

207

- Sorted by growth metrics

208

209

#### Usage Examples

210

211

```python

212

# Software industry analysis

213

software_industry = yf.Industry('software')

214

215

# Check parent sector

216

print(f"Industry: Software")

217

print(f"Parent Sector: {software_industry.sector_name} ({software_industry.sector_key})")

218

219

# Top performing companies

220

top_performers = software_industry.top_performing_companies

221

print(f"\nTop Performing Software Companies:")

222

print(top_performers[['symbol', 'name', 'change_percent']].head())

223

224

# High growth companies

225

growth_companies = software_industry.top_growth_companies

226

print(f"\nHigh Growth Software Companies:")

227

print(growth_companies[['symbol', 'name', 'revenue_growth']].head())

228

229

# Create watchlist from top performers

230

watchlist_symbols = top_performers['symbol'].head(10).tolist()

231

print(f"\nWatchlist: {watchlist_symbols}")

232

```

233

234

## Advanced Market Analysis Patterns

235

236

### Cross-Sector Comparison

237

238

```python

239

def compare_sectors(sector_keys, metric='performance'):

240

"""Compare multiple sectors across key metrics."""

241

242

sector_data = {}

243

244

for sector_key in sector_keys:

245

sector = yf.Sector(sector_key)

246

sector_data[sector_key] = {

247

'top_etfs': sector.top_etfs,

248

'top_funds': sector.top_mutual_funds,

249

'industries': sector.industries

250

}

251

252

# Create comparison summary

253

comparison = {}

254

for sector_key, data in sector_data.items():

255

etf_count = len(data['top_etfs'])

256

fund_count = len(data['top_funds'])

257

industry_count = len(data['industries']) if not data['industries'].empty else 0

258

259

comparison[sector_key] = {

260

'etf_options': etf_count,

261

'fund_options': fund_count,

262

'industry_diversity': industry_count

263

}

264

265

return comparison, sector_data

266

267

# Usage

268

sectors = ['technology', 'healthcare', 'finance', 'energy']

269

comparison, detailed_data = compare_sectors(sectors)

270

271

for sector, metrics in comparison.items():

272

print(f"{sector.capitalize()}: {metrics['etf_options']} ETFs, "

273

f"{metrics['fund_options']} funds, {metrics['industry_diversity']} industries")

274

```

275

276

### Industry Leadership Analysis

277

278

```python

279

def analyze_industry_leaders(industry_key, top_n=5):

280

"""Analyze leadership and growth trends within an industry."""

281

282

industry = yf.Industry(industry_key)

283

284

# Get top companies by different metrics

285

top_performers = industry.top_performing_companies.head(top_n)

286

growth_leaders = industry.top_growth_companies.head(top_n)

287

288

# Create detailed analysis

289

analysis = {

290

'industry': industry_key,

291

'sector': industry.sector_name,

292

'performance_leaders': [],

293

'growth_leaders': [],

294

'overlap': []

295

}

296

297

# Process performance leaders

298

for _, company in top_performers.iterrows():

299

analysis['performance_leaders'].append({

300

'symbol': company['symbol'],

301

'name': company['name'],

302

'performance_metric': company.get('change_percent', 0)

303

})

304

305

# Process growth leaders

306

for _, company in growth_leaders.iterrows():

307

analysis['growth_leaders'].append({

308

'symbol': company['symbol'],

309

'name': company['name'],

310

'growth_metric': company.get('revenue_growth', 0)

311

})

312

313

# Find overlap between performance and growth leaders

314

perf_symbols = set(top_performers['symbol'])

315

growth_symbols = set(growth_leaders['symbol'])

316

overlap_symbols = perf_symbols.intersection(growth_symbols)

317

318

analysis['overlap'] = list(overlap_symbols)

319

320

return analysis

321

322

# Usage

323

software_analysis = analyze_industry_leaders('software', top_n=10)

324

print(f"Software Industry Analysis:")

325

print(f"Performance Leaders: {[comp['symbol'] for comp in software_analysis['performance_leaders']]}")

326

print(f"Growth Leaders: {[comp['symbol'] for comp in software_analysis['growth_leaders']]}")

327

print(f"Both Performance & Growth: {software_analysis['overlap']}")

328

```

329

330

### Market Breadth Analysis

331

332

```python

333

def analyze_market_breadth(market_key='US'):

334

"""Analyze market breadth indicators."""

335

336

market = yf.Market(market_key)

337

summary = market.summary

338

339

breadth_metrics = {}

340

341

for exchange, data in summary.items():

342

advancing = data.get('advancing_issues', 0)

343

declining = data.get('declining_issues', 0)

344

unchanged = data.get('unchanged_issues', 0)

345

total_volume = data.get('total_volume', 0)

346

347

total_issues = advancing + declining + unchanged

348

349

if total_issues > 0:

350

breadth_metrics[exchange] = {

351

'advance_decline_ratio': advancing / declining if declining > 0 else float('inf'),

352

'advance_percent': (advancing / total_issues) * 100,

353

'decline_percent': (declining / total_issues) * 100,

354

'unchanged_percent': (unchanged / total_issues) * 100,

355

'total_volume': total_volume,

356

'breadth_momentum': 'Positive' if advancing > declining else 'Negative'

357

}

358

359

# Overall market breadth

360

total_advancing = sum(data.get('advancing_issues', 0) for data in summary.values())

361

total_declining = sum(data.get('declining_issues', 0) for data in summary.values())

362

363

overall_breadth = {

364

'overall_ad_ratio': total_advancing / total_declining if total_declining > 0 else float('inf'),

365

'market_sentiment': 'Bullish' if total_advancing > total_declining else 'Bearish',

366

'by_exchange': breadth_metrics

367

}

368

369

return overall_breadth

370

371

# Usage

372

breadth_analysis = analyze_market_breadth()

373

print(f"Overall A/D Ratio: {breadth_analysis['overall_ad_ratio']:.2f}")

374

print(f"Market Sentiment: {breadth_analysis['market_sentiment']}")

375

376

for exchange, metrics in breadth_analysis['by_exchange'].items():

377

print(f"{exchange}: {metrics['advance_percent']:.1f}% advancing, "

378

f"momentum: {metrics['breadth_momentum']}")

379

```

380

381

### Sector Rotation Analysis

382

383

```python

384

def analyze_sector_rotation(sectors, timeframe='1mo'):

385

"""Analyze sector rotation patterns by comparing sector ETF performance."""

386

387

sector_analysis = {}

388

389

for sector_key in sectors:

390

sector = yf.Sector(sector_key)

391

top_etfs = sector.top_etfs

392

393

if top_etfs:

394

# Get the primary ETF (usually first one) for sector representation

395

primary_etf = list(top_etfs.keys())[0]

396

397

# Get ETF performance data

398

etf_ticker = yf.Ticker(primary_etf)

399

history = etf_ticker.history(period=timeframe)

400

401

if not history.empty:

402

total_return = (history['Close'].iloc[-1] / history['Close'].iloc[0] - 1) * 100

403

volatility = history['Close'].pct_change().std() * 100

404

405

sector_analysis[sector_key] = {

406

'primary_etf': primary_etf,

407

'etf_name': top_etfs[primary_etf],

408

'total_return': total_return,

409

'volatility': volatility,

410

'risk_adjusted_return': total_return / volatility if volatility > 0 else 0

411

}

412

413

# Rank sectors by performance

414

sorted_sectors = sorted(sector_analysis.items(),

415

key=lambda x: x[1]['total_return'], reverse=True)

416

417

rotation_analysis = {

418

'timeframe': timeframe,

419

'leader_sectors': sorted_sectors[:3],

420

'laggard_sectors': sorted_sectors[-3:],

421

'all_sectors': dict(sorted_sectors)

422

}

423

424

return rotation_analysis

425

426

# Usage

427

sectors = ['technology', 'healthcare', 'finance', 'energy', 'utilities', 'materials']

428

rotation = analyze_sector_rotation(sectors, timeframe='3mo')

429

430

print("Sector Rotation Analysis (3 months):")

431

print("\nLeading Sectors:")

432

for sector, data in rotation['leader_sectors']:

433

print(f" {sector.capitalize()}: {data['total_return']:+.2f}% "

434

f"({data['primary_etf']})")

435

436

print("\nLagging Sectors:")

437

for sector, data in rotation['laggard_sectors']:

438

print(f" {sector.capitalize()}: {data['total_return']:+.2f}% "

439

f"({data['primary_etf']})")

440

```

441

442

### Market Timing Indicators

443

444

```python

445

def generate_market_timing_signals(market_key='US'):

446

"""Generate market timing signals based on breadth and sector data."""

447

448

market = yf.Market(market_key)

449

status = market.status

450

summary = market.summary

451

452

signals = {

453

'timestamp': status.get('current_time'),

454

'market_state': status.get('market_state'),

455

'signals': []

456

}

457

458

# Breadth-based signals

459

total_advancing = sum(data.get('advancing_issues', 0) for data in summary.values())

460

total_declining = sum(data.get('declining_issues', 0) for data in summary.values())

461

462

if total_advancing > 0 and total_declining > 0:

463

ad_ratio = total_advancing / total_declining

464

465

if ad_ratio > 2.0:

466

signals['signals'].append({

467

'type': 'BULLISH',

468

'indicator': 'Advance/Decline Ratio',

469

'value': ad_ratio,

470

'description': 'Strong market breadth - many stocks advancing'

471

})

472

elif ad_ratio < 0.5:

473

signals['signals'].append({

474

'type': 'BEARISH',

475

'indicator': 'Advance/Decline Ratio',

476

'value': ad_ratio,

477

'description': 'Weak market breadth - many stocks declining'

478

})

479

480

# Volume-based signals

481

total_volume = sum(data.get('total_volume', 0) for data in summary.values())

482

483

# Note: This would typically compare to historical averages

484

# For demonstration, using arbitrary thresholds

485

if total_volume > 5_000_000_000: # 5B+ shares

486

signals['signals'].append({

487

'type': 'BULLISH',

488

'indicator': 'High Volume',

489

'value': total_volume,

490

'description': 'High trading volume indicates strong participation'

491

})

492

493

# Market state signals

494

if status.get('is_open'):

495

signals['signals'].append({

496

'type': 'NEUTRAL',

497

'indicator': 'Market State',

498

'value': status.get('market_state'),

499

'description': f"Market is currently {status.get('market_state').lower()}"

500

})

501

502

return signals

503

504

# Usage

505

timing_signals = generate_market_timing_signals()

506

print(f"Market Timing Analysis - {timing_signals['timestamp']}")

507

print(f"Market State: {timing_signals['market_state']}")

508

509

for signal in timing_signals['signals']:

510

print(f"{signal['type']}: {signal['indicator']} - {signal['description']}")

511

```

512

513

## Integration with Other yfinance Features

514

515

### Portfolio Sector Allocation

516

517

```python

518

def analyze_portfolio_sector_allocation(portfolio_symbols):

519

"""Analyze sector allocation of a portfolio."""

520

521

portfolio_sectors = {}

522

total_value = 0

523

524

for symbol in portfolio_symbols:

525

ticker = yf.Ticker(symbol)

526

info = ticker.info

527

528

sector = info.get('sector', 'Unknown')

529

market_cap = info.get('marketCap', 0)

530

531

if sector not in portfolio_sectors:

532

portfolio_sectors[sector] = {

533

'symbols': [],

534

'total_market_cap': 0,

535

'count': 0

536

}

537

538

portfolio_sectors[sector]['symbols'].append(symbol)

539

portfolio_sectors[sector]['total_market_cap'] += market_cap

540

portfolio_sectors[sector]['count'] += 1

541

total_value += market_cap

542

543

# Calculate allocations

544

for sector_data in portfolio_sectors.values():

545

sector_data['allocation_percent'] = (

546

sector_data['total_market_cap'] / total_value * 100

547

if total_value > 0 else 0

548

)

549

550

return portfolio_sectors

551

552

# Usage

553

portfolio = ["AAPL", "GOOGL", "MSFT", "JNJ", "JPM", "PFE", "XOM", "WMT"]

554

sector_allocation = analyze_portfolio_sector_allocation(portfolio)

555

556

print("Portfolio Sector Allocation:")

557

for sector, data in sector_allocation.items():

558

print(f"{sector}: {data['allocation_percent']:.1f}% "

559

f"({data['count']} stocks: {', '.join(data['symbols'])})")

560

```

561

562

### Sector-Based Stock Screening

563

564

```python

565

def screen_stocks_by_sector_performance(sector_key, performance_threshold=5.0):

566

"""Screen stocks within high-performing sectors."""

567

568

# First, analyze the sector

569

sector = yf.Sector(sector_key)

570

industries = sector.industries

571

572

if industries.empty:

573

return []

574

575

# Get top performing industries (assuming performance column exists)

576

top_industries = industries.nlargest(3, 'performance') if 'performance' in industries.columns else industries.head(3)

577

578

screened_stocks = []

579

580

for industry_name in top_industries.index:

581

try:

582

# Create industry object (this assumes industry key matches name)

583

industry = yf.Industry(industry_name.lower().replace(' ', '_'))

584

585

# Get top performing companies

586

top_companies = industry.top_performing_companies

587

588

# Filter by performance threshold

589

if not top_companies.empty and 'change_percent' in top_companies.columns:

590

filtered_companies = top_companies[

591

top_companies['change_percent'] > performance_threshold

592

]

593

594

for _, company in filtered_companies.iterrows():

595

screened_stocks.append({

596

'symbol': company['symbol'],

597

'name': company['name'],

598

'sector': sector_key,

599

'industry': industry_name,

600

'performance': company['change_percent']

601

})

602

603

except Exception as e:

604

print(f"Error processing industry {industry_name}: {e}")

605

continue

606

607

return screened_stocks

608

609

# Usage

610

tech_performers = screen_stocks_by_sector_performance('technology', performance_threshold=3.0)

611

print("High-performing technology stocks:")

612

for stock in tech_performers[:10]: # Top 10

613

print(f"{stock['symbol']}: {stock['performance']:+.2f}% ({stock['industry']})")

614

```