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
```