or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

broker-client.mddata-client.mdindex.mdtrading-client.md

data-client.mddocs/

0

# Data Client

1

2

The Data Client provides comprehensive access to historical and real-time market data across multiple asset classes including stocks, cryptocurrencies, options, and news. It supports both REST API calls for historical data and WebSocket streams for real-time data feeds.

3

4

## Historical Data Clients

5

6

### StockHistoricalDataClient

7

8

```python { .api }

9

from alpaca.data.historical import StockHistoricalDataClient

10

11

class StockHistoricalDataClient(RESTClient):

12

def __init__(

13

self,

14

api_key: Optional[str] = None,

15

secret_key: Optional[str] = None,

16

oauth_token: Optional[str] = None,

17

use_basic_auth: bool = False,

18

raw_data: bool = False,

19

url_override: Optional[str] = None,

20

sandbox: bool = False,

21

) -> None:

22

"""

23

Initialize stock historical data client.

24

25

Args:

26

api_key: Alpaca API key

27

secret_key: Alpaca API secret

28

oauth_token: OAuth token for user-on-behalf access

29

use_basic_auth: Use basic auth headers (for broker sandbox)

30

raw_data: Return raw API responses instead of models

31

url_override: Override base URL for testing

32

sandbox: Use sandbox environment

33

"""

34

```

35

36

#### Basic Setup

37

38

```python { .api }

39

# Standard data client

40

data_client = StockHistoricalDataClient(

41

api_key="your-api-key",

42

secret_key="your-secret-key"

43

)

44

45

# OAuth-based client

46

data_client = StockHistoricalDataClient(

47

oauth_token="user-oauth-token"

48

)

49

50

# Sandbox client (for broker API users)

51

data_client = StockHistoricalDataClient(

52

api_key="broker-sandbox-key",

53

secret_key="broker-sandbox-secret",

54

use_basic_auth=True,

55

sandbox=True

56

)

57

```

58

59

### CryptoHistoricalDataClient

60

61

```python { .api }

62

from alpaca.data.historical import CryptoHistoricalDataClient

63

64

class CryptoHistoricalDataClient(RESTClient):

65

def __init__(

66

self,

67

api_key: Optional[str] = None,

68

secret_key: Optional[str] = None,

69

oauth_token: Optional[str] = None,

70

use_basic_auth: bool = False,

71

raw_data: bool = False,

72

url_override: Optional[str] = None,

73

sandbox: bool = False,

74

) -> None:

75

"""Initialize crypto historical data client with same parameters as stock client."""

76

```

77

78

### OptionHistoricalDataClient

79

80

```python { .api }

81

from alpaca.data.historical import OptionHistoricalDataClient

82

83

class OptionHistoricalDataClient(RESTClient):

84

def __init__(

85

self,

86

api_key: Optional[str] = None,

87

secret_key: Optional[str] = None,

88

oauth_token: Optional[str] = None,

89

use_basic_auth: bool = False,

90

raw_data: bool = False,

91

url_override: Optional[str] = None,

92

sandbox: bool = False,

93

) -> None:

94

"""Initialize options historical data client with same parameters as stock client."""

95

```

96

97

### NewsClient

98

99

```python { .api }

100

from alpaca.data.historical import NewsClient

101

102

class NewsClient(RESTClient):

103

def __init__(

104

self,

105

api_key: Optional[str] = None,

106

secret_key: Optional[str] = None,

107

oauth_token: Optional[str] = None,

108

use_basic_auth: bool = False,

109

raw_data: bool = False,

110

url_override: Optional[str] = None,

111

sandbox: bool = False,

112

) -> None:

113

"""Initialize news data client with same parameters as other clients."""

114

```

115

116

### ScreenerClient

117

118

```python { .api }

119

from alpaca.data.historical import ScreenerClient

120

121

class ScreenerClient(RESTClient):

122

def __init__(

123

self,

124

api_key: Optional[str] = None,

125

secret_key: Optional[str] = None,

126

oauth_token: Optional[str] = None,

127

use_basic_auth: bool = False,

128

raw_data: bool = False,

129

url_override: Optional[str] = None,

130

sandbox: bool = False,

131

) -> None:

132

"""Initialize screener client for market scanning data."""

133

```

134

135

## TimeFrame System

136

137

### TimeFrame Class

138

139

```python { .api }

140

from alpaca.data.timeframe import TimeFrame, TimeFrameUnit

141

142

class TimeFrame:

143

def __init__(self, amount: int, unit: TimeFrameUnit) -> None:

144

"""

145

Create a timeframe for data aggregation.

146

147

Args:

148

amount: Number of time units (1-59 for minutes, 1-23 for hours, etc.)

149

unit: Time unit (Minute, Hour, Day, Week, Month)

150

"""

151

152

@property

153

def amount(self) -> int:

154

"""Number of time units."""

155

156

@property

157

def unit(self) -> TimeFrameUnit:

158

"""Time unit type."""

159

160

@property

161

def value(self) -> str:

162

"""String representation for API (e.g., '5Min', '1Day')."""

163

164

# Predefined timeframes

165

TimeFrame.Minute # 1-minute bars

166

TimeFrame.Hour # 1-hour bars

167

TimeFrame.Day # 1-day bars

168

TimeFrame.Week # 1-week bars

169

TimeFrame.Month # 1-month bars

170

```

171

172

### TimeFrameUnit Enum

173

174

```python { .api }

175

from alpaca.data.timeframe import TimeFrameUnit

176

177

class TimeFrameUnit(str, Enum):

178

Minute = "Min" # Minute intervals (1-59)

179

Hour = "Hour" # Hour intervals (1-23)

180

Day = "Day" # Daily intervals (1 only)

181

Week = "Week" # Weekly intervals (1 only)

182

Month = "Month" # Monthly intervals (1, 2, 3, 6, 12)

183

```

184

185

**Usage Examples:**

186

187

```python { .api }

188

# Create custom timeframes

189

five_min = TimeFrame(5, TimeFrameUnit.Minute)

190

four_hour = TimeFrame(4, TimeFrameUnit.Hour)

191

quarterly = TimeFrame(3, TimeFrameUnit.Month)

192

193

# Use predefined timeframes

194

minute_tf = TimeFrame.Minute

195

daily_tf = TimeFrame.Day

196

197

print(f"Timeframe: {five_min.value}") # Output: "5Min"

198

```

199

200

## Stock Market Data

201

202

### Historical Bars (OHLCV)

203

204

#### get_stock_bars()

205

206

```python { .api }

207

def get_stock_bars(

208

self,

209

request: StockBarsRequest

210

) -> Union[BarSet, RawData]:

211

"""

212

Get historical bar data for stocks.

213

214

Args:

215

request: Bar request parameters

216

217

Returns:

218

BarSet: Time-series bar data with OHLCV information

219

"""

220

```

221

222

#### StockBarsRequest

223

224

```python { .api }

225

from alpaca.data.requests import StockBarsRequest

226

from alpaca.data.timeframe import TimeFrame

227

from alpaca.data.enums import Adjustment, DataFeed

228

from datetime import datetime

229

230

class StockBarsRequest(BaseBarsRequest):

231

def __init__(

232

self,

233

symbol_or_symbols: Union[str, List[str]], # Required: symbols to retrieve

234

timeframe: TimeFrame, # Required: bar aggregation period

235

start: Optional[datetime] = None, # Start time (UTC)

236

end: Optional[datetime] = None, # End time (UTC, defaults to now)

237

limit: Optional[int] = None, # Max bars to return

238

adjustment: Optional[Adjustment] = None, # Corporate action adjustment

239

feed: Optional[DataFeed] = None, # Data feed (IEX, SIP, etc.)

240

sort: Optional[Sort] = None, # ASC or DESC

241

currency: Optional[SupportedCurrencies] = None # Currency (defaults to USD)

242

):

243

```

244

245

#### Adjustment Enum

246

247

```python { .api }

248

from alpaca.data.enums import Adjustment

249

250

class Adjustment(str, Enum):

251

RAW = "raw" # No adjustments

252

SPLIT = "split" # Split-adjusted only

253

DIVIDEND = "dividend" # Dividend-adjusted only

254

ALL = "all" # Both split and dividend adjusted

255

```

256

257

#### DataFeed Enum

258

259

```python { .api }

260

from alpaca.data.enums import DataFeed

261

262

class DataFeed(str, Enum):

263

IEX = "iex" # IEX data feed

264

SIP = "sip" # Securities Information Processor (premium)

265

OTC = "otc" # Over-the-counter data

266

ERSX = "ersx" # ERSX data feed

267

MEMX = "memx" # Members Exchange

268

OPRA = "opra" # Options Price Reporting Authority

269

INDICATIVE = "indicative" # Indicative pricing

270

```

271

272

**Usage Examples:**

273

274

```python { .api }

275

from alpaca.data.requests import StockBarsRequest

276

from alpaca.data.timeframe import TimeFrame, TimeFrameUnit

277

from alpaca.data.enums import Adjustment, DataFeed

278

from datetime import datetime, timedelta

279

280

# Get 1-minute bars for single stock

281

bars_request = StockBarsRequest(

282

symbol_or_symbols="AAPL",

283

timeframe=TimeFrame.Minute,

284

start=datetime.now() - timedelta(hours=6),

285

end=datetime.now()

286

)

287

bars = data_client.get_stock_bars(bars_request)

288

289

# Get daily bars for multiple stocks with adjustments

290

bars_request = StockBarsRequest(

291

symbol_or_symbols=["AAPL", "TSLA", "MSFT", "GOOGL"],

292

timeframe=TimeFrame.Day,

293

start=datetime(2023, 1, 1),

294

end=datetime(2023, 12, 31),

295

adjustment=Adjustment.ALL,

296

feed=DataFeed.SIP

297

)

298

bars = data_client.get_stock_bars(bars_request)

299

300

# Get 5-minute bars with limit

301

bars_request = StockBarsRequest(

302

symbol_or_symbols="SPY",

303

timeframe=TimeFrame(5, TimeFrameUnit.Minute),

304

limit=1000,

305

sort=Sort.DESC # Most recent first

306

)

307

bars = data_client.get_stock_bars(bars_request)

308

```

309

310

#### Bar Model

311

312

```python { .api }

313

from alpaca.data.models import Bar

314

315

class Bar:

316

"""OHLCV bar data for a single time period."""

317

318

symbol: str # Stock symbol

319

timestamp: datetime # Bar timestamp (UTC)

320

open: float # Opening price

321

high: float # High price

322

low: float # Low price

323

close: float # Closing price

324

volume: int # Trading volume

325

trade_count: Optional[int] # Number of trades

326

vwap: Optional[float] # Volume-weighted average price

327

```

328

329

#### BarSet Model

330

331

```python { .api }

332

from alpaca.data.models import BarSet

333

334

class BarSet:

335

"""Collection of bars with time-series functionality."""

336

337

# Dictionary access: bars["AAPL"] returns List[Bar]

338

# Pandas integration: bars.df returns DataFrame

339

# Time-series operations available

340

341

def __getitem__(self, symbol: str) -> List[Bar]:

342

"""Get bars for specific symbol."""

343

344

@property

345

def df(self) -> pd.DataFrame:

346

"""Convert to pandas DataFrame with MultiIndex."""

347

348

@property

349

def symbols(self) -> List[str]:

350

"""Get all symbols in the bar set."""

351

```

352

353

**Working with Bar Data:**

354

355

```python { .api }

356

# Access bars by symbol

357

bars = data_client.get_stock_bars(bars_request)

358

aapl_bars = bars["AAPL"]

359

360

print(f"Retrieved {len(aapl_bars)} bars for AAPL")

361

for bar in aapl_bars[-5:]: # Last 5 bars

362

print(f"{bar.timestamp}: O:{bar.open} H:{bar.high} L:{bar.low} C:{bar.close} V:{bar.volume}")

363

364

# Convert to pandas for analysis

365

df = bars.df

366

print(df.head())

367

print(f"Symbols: {bars.symbols}")

368

369

# Calculate returns

370

df['returns'] = df.groupby('symbol')['close'].pct_change()

371

print(f"Average daily return: {df.groupby('symbol')['returns'].mean()}")

372

```

373

374

### Quotes (Bid/Ask Data)

375

376

#### get_stock_quotes()

377

378

```python { .api }

379

def get_stock_quotes(

380

self,

381

request: StockQuotesRequest

382

) -> Union[QuoteSet, RawData]:

383

"""

384

Get historical quote data (bid/ask) for stocks.

385

386

Args:

387

request: Quote request parameters

388

389

Returns:

390

QuoteSet: Time-series quote data

391

"""

392

```

393

394

#### StockQuotesRequest

395

396

```python { .api }

397

from alpaca.data.requests import StockQuotesRequest

398

399

class StockQuotesRequest(BaseTimeseriesDataRequest):

400

def __init__(

401

self,

402

symbol_or_symbols: Union[str, List[str]], # Required: symbols

403

start: Optional[datetime] = None, # Start time (UTC)

404

end: Optional[datetime] = None, # End time (UTC)

405

limit: Optional[int] = None, # Max quotes to return

406

feed: Optional[DataFeed] = None, # Data feed

407

sort: Optional[Sort] = None, # Sort order

408

currency: Optional[SupportedCurrencies] = None

409

):

410

```

411

412

#### Quote Model

413

414

```python { .api }

415

from alpaca.data.models import Quote

416

417

class Quote:

418

"""Bid/ask quote data."""

419

420

symbol: str # Stock symbol

421

timestamp: datetime # Quote timestamp (UTC)

422

bid_exchange: str # Bid exchange code

423

bid_price: float # Bid price

424

bid_size: int # Bid size (shares)

425

ask_exchange: str # Ask exchange code

426

ask_price: float # Ask price

427

ask_size: int # Ask size (shares)

428

conditions: Optional[List[str]] # Quote conditions/flags

429

```

430

431

**Usage Examples:**

432

433

```python { .api }

434

# Get recent quotes

435

quotes_request = StockQuotesRequest(

436

symbol_or_symbols="AAPL",

437

start=datetime.now() - timedelta(hours=1),

438

limit=1000

439

)

440

quotes = data_client.get_stock_quotes(quotes_request)

441

442

# Analyze bid-ask spread

443

aapl_quotes = quotes["AAPL"]

444

for quote in aapl_quotes[-10:]:

445

spread = quote.ask_price - quote.bid_price

446

spread_pct = (spread / quote.ask_price) * 100

447

print(f"{quote.timestamp}: Bid ${quote.bid_price} Ask ${quote.ask_price} Spread {spread_pct:.3f}%")

448

```

449

450

### Trades (Individual Transactions)

451

452

#### get_stock_trades()

453

454

```python { .api }

455

def get_stock_trades(

456

self,

457

request: StockTradesRequest

458

) -> Union[TradeSet, RawData]:

459

"""

460

Get historical trade data for stocks.

461

462

Args:

463

request: Trade request parameters

464

465

Returns:

466

TradeSet: Time-series trade execution data

467

"""

468

```

469

470

#### StockTradesRequest

471

472

```python { .api }

473

from alpaca.data.requests import StockTradesRequest

474

475

class StockTradesRequest(BaseTimeseriesDataRequest):

476

def __init__(

477

self,

478

symbol_or_symbols: Union[str, List[str]], # Required: symbols

479

start: Optional[datetime] = None, # Start time (UTC)

480

end: Optional[datetime] = None, # End time (UTC)

481

limit: Optional[int] = None, # Max trades to return

482

feed: Optional[DataFeed] = None, # Data feed

483

sort: Optional[Sort] = None, # Sort order

484

currency: Optional[SupportedCurrencies] = None

485

):

486

```

487

488

#### Trade Model

489

490

```python { .api }

491

from alpaca.data.models import Trade

492

493

class Trade:

494

"""Individual trade execution data."""

495

496

symbol: str # Stock symbol

497

timestamp: datetime # Trade timestamp (UTC)

498

exchange: str # Exchange code

499

price: float # Trade price

500

size: int # Trade size (shares)

501

trade_id: Optional[str] # Unique trade ID

502

conditions: Optional[List[str]] # Trade conditions/flags

503

```

504

505

**Usage Examples:**

506

507

```python { .api }

508

# Get recent trades for analysis

509

trades_request = StockTradesRequest(

510

symbol_or_symbols="TSLA",

511

start=datetime.now() - timedelta(minutes=30),

512

limit=5000

513

)

514

trades = data_client.get_stock_trades(trades_request)

515

516

# Analyze trade activity

517

tsla_trades = trades["TSLA"]

518

total_volume = sum(trade.size for trade in tsla_trades)

519

vwap = sum(trade.price * trade.size for trade in tsla_trades) / total_volume

520

521

print(f"Trades: {len(tsla_trades)}, Volume: {total_volume:,}, VWAP: ${vwap:.2f}")

522

```

523

524

### Latest Market Data

525

526

#### get_stock_latest_bar()

527

528

```python { .api }

529

def get_stock_latest_bar(

530

self,

531

request: StockLatestBarRequest

532

) -> Union[Dict[str, Bar], RawData]:

533

"""

534

Get latest bar for stocks.

535

536

Args:

537

request: Latest bar request

538

539

Returns:

540

Dict[str, Bar]: Latest bar for each symbol

541

"""

542

```

543

544

#### get_stock_latest_quote()

545

546

```python { .api }

547

def get_stock_latest_quote(

548

self,

549

request: StockLatestQuoteRequest

550

) -> Union[Dict[str, Quote], RawData]:

551

"""

552

Get latest quote for stocks.

553

554

Args:

555

request: Latest quote request

556

557

Returns:

558

Dict[str, Quote]: Latest quote for each symbol

559

"""

560

```

561

562

#### get_stock_latest_trade()

563

564

```python { .api }

565

def get_stock_latest_trade(

566

self,

567

request: StockLatestTradeRequest

568

) -> Union[Dict[str, Trade], RawData]:

569

"""

570

Get latest trade for stocks.

571

572

Args:

573

request: Latest trade request

574

575

Returns:

576

Dict[str, Trade]: Latest trade for each symbol

577

"""

578

```

579

580

#### Latest Data Request Classes

581

582

```python { .api }

583

from alpaca.data.requests import (

584

StockLatestBarRequest, StockLatestQuoteRequest, StockLatestTradeRequest

585

)

586

587

class StockLatestBarRequest(NonEmptyRequest):

588

def __init__(

589

self,

590

symbol_or_symbols: Union[str, List[str]], # Required: symbols

591

feed: Optional[DataFeed] = None, # Data feed

592

currency: Optional[SupportedCurrencies] = None

593

):

594

595

class StockLatestQuoteRequest(NonEmptyRequest):

596

def __init__(

597

self,

598

symbol_or_symbols: Union[str, List[str]], # Required: symbols

599

feed: Optional[DataFeed] = None, # Data feed

600

currency: Optional[SupportedCurrencies] = None

601

):

602

603

class StockLatestTradeRequest(NonEmptyRequest):

604

def __init__(

605

self,

606

symbol_or_symbols: Union[str, List[str]], # Required: symbols

607

feed: Optional[DataFeed] = None, # Data feed

608

currency: Optional[SupportedCurrencies] = None

609

):

610

```

611

612

**Usage Examples:**

613

614

```python { .api }

615

# Get latest bars for portfolio monitoring

616

latest_bars = data_client.get_stock_latest_bar(

617

StockLatestBarRequest(

618

symbol_or_symbols=["AAPL", "TSLA", "MSFT", "GOOGL"],

619

feed=DataFeed.IEX

620

)

621

)

622

623

for symbol, bar in latest_bars.items():

624

print(f"{symbol}: ${bar.close} (Vol: {bar.volume:,})")

625

626

# Get latest quotes for order placement

627

latest_quotes = data_client.get_stock_latest_quote(

628

StockLatestQuoteRequest(symbol_or_symbols="AAPL")

629

)

630

631

aapl_quote = latest_quotes["AAPL"]

632

print(f"AAPL Bid: ${aapl_quote.bid_price} x {aapl_quote.bid_size}")

633

print(f"AAPL Ask: ${aapl_quote.ask_price} x {aapl_quote.ask_size}")

634

635

# Get latest trades for execution analysis

636

latest_trades = data_client.get_stock_latest_trade(

637

StockLatestTradeRequest(symbol_or_symbols="SPY")

638

)

639

640

spy_trade = latest_trades["SPY"]

641

print(f"SPY Last: ${spy_trade.price} @ {spy_trade.timestamp}")

642

```

643

644

### Market Snapshots

645

646

#### get_stock_snapshot()

647

648

```python { .api }

649

def get_stock_snapshot(

650

self,

651

request: StockSnapshotRequest

652

) -> Union[Dict[str, Snapshot], RawData]:

653

"""

654

Get comprehensive market snapshot for stocks.

655

656

Args:

657

request: Snapshot request parameters

658

659

Returns:

660

Dict[str, Snapshot]: Complete market data snapshot for each symbol

661

"""

662

```

663

664

#### StockSnapshotRequest

665

666

```python { .api }

667

from alpaca.data.requests import StockSnapshotRequest

668

669

class StockSnapshotRequest(NonEmptyRequest):

670

def __init__(

671

self,

672

symbol_or_symbols: Union[str, List[str]], # Required: symbols

673

feed: Optional[DataFeed] = None, # Data feed

674

currency: Optional[SupportedCurrencies] = None

675

):

676

```

677

678

#### Snapshot Model

679

680

```python { .api }

681

from alpaca.data.models import Snapshot

682

683

class Snapshot:

684

"""Comprehensive market snapshot combining all data types."""

685

686

symbol: str # Stock symbol

687

latest_trade: Optional[Trade] # Most recent trade

688

latest_quote: Optional[Quote] # Current bid/ask

689

minute_bar: Optional[Bar] # Current minute bar

690

daily_bar: Optional[Bar] # Current daily bar

691

prev_daily_bar: Optional[Bar] # Previous day's bar

692

```

693

694

**Usage Examples:**

695

696

```python { .api }

697

# Get comprehensive market snapshot

698

snapshot = data_client.get_stock_snapshot(

699

StockSnapshotRequest(

700

symbol_or_symbols=["AAPL", "TSLA", "SPY"],

701

feed=DataFeed.IEX

702

)

703

)

704

705

for symbol, snap in snapshot.items():

706

print(f"\n{symbol} Snapshot:")

707

708

if snap.latest_trade:

709

print(f" Last Trade: ${snap.latest_trade.price} @ {snap.latest_trade.timestamp}")

710

711

if snap.latest_quote:

712

spread = snap.latest_quote.ask_price - snap.latest_quote.bid_price

713

print(f" Quote: ${snap.latest_quote.bid_price} x ${snap.latest_quote.ask_price} (${spread:.2f})")

714

715

if snap.daily_bar and snap.prev_daily_bar:

716

daily_change = snap.daily_bar.close - snap.prev_daily_bar.close

717

daily_change_pct = (daily_change / snap.prev_daily_bar.close) * 100

718

print(f" Daily: ${snap.daily_bar.close} ({daily_change_pct:+.2f}%)")

719

print(f" Volume: {snap.daily_bar.volume:,}")

720

```

721

722

## Cryptocurrency Data

723

724

The cryptocurrency clients follow the same patterns as stock data with crypto-specific symbols and features.

725

726

### CryptoHistoricalDataClient Methods

727

728

```python { .api }

729

from alpaca.data.historical import CryptoHistoricalDataClient

730

from alpaca.data.requests import (

731

CryptoBarsRequest, CryptoQuotesRequest, CryptoTradesRequest,

732

CryptoLatestBarRequest, CryptoLatestQuoteRequest, CryptoLatestTradeRequest,

733

CryptoSnapshotRequest, CryptoLatestOrderbookRequest

734

)

735

736

crypto_client = CryptoHistoricalDataClient(api_key="key", secret_key="secret")

737

738

# Same methods as stock client but with crypto request types

739

crypto_client.get_crypto_bars(CryptoBarsRequest(...))

740

crypto_client.get_crypto_quotes(CryptoQuotesRequest(...))

741

crypto_client.get_crypto_trades(CryptoTradesRequest(...))

742

crypto_client.get_crypto_latest_bar(CryptoLatestBarRequest(...))

743

crypto_client.get_crypto_latest_quote(CryptoLatestQuoteRequest(...))

744

crypto_client.get_crypto_latest_trade(CryptoLatestTradeRequest(...))

745

crypto_client.get_crypto_snapshot(CryptoSnapshotRequest(...))

746

747

# Crypto-specific: order book data

748

crypto_client.get_crypto_latest_orderbook(CryptoLatestOrderbookRequest(...))

749

```

750

751

### Crypto Symbols and Usage

752

753

```python { .api }

754

# Crypto symbols use / format: BASE/QUOTE

755

crypto_symbols = ["BTC/USD", "ETH/USD", "LTC/USD", "BCH/USD", "DOGE/USD"]

756

757

# Get crypto bars

758

crypto_bars = crypto_client.get_crypto_bars(

759

CryptoBarsRequest(

760

symbol_or_symbols=crypto_symbols,

761

timeframe=TimeFrame.Hour,

762

start=datetime.now() - timedelta(days=7)

763

)

764

)

765

766

# Get latest crypto quotes

767

crypto_quotes = crypto_client.get_crypto_latest_quote(

768

CryptoLatestQuoteRequest(symbol_or_symbols="BTC/USD")

769

)

770

771

btc_quote = crypto_quotes["BTC/USD"]

772

print(f"BTC/USD: ${btc_quote.bid_price:.2f} / ${btc_quote.ask_price:.2f}")

773

```

774

775

### Crypto Order Book Data

776

777

```python { .api }

778

from alpaca.data.requests import CryptoLatestOrderbookRequest

779

780

# Get order book depth

781

orderbook = crypto_client.get_crypto_latest_orderbook(

782

CryptoLatestOrderbookRequest(symbol_or_symbols="BTC/USD")

783

)

784

785

btc_book = orderbook["BTC/USD"]

786

print("Top 5 Bids:")

787

for bid in btc_book.bids[:5]:

788

print(f" ${bid.price:.2f} x {bid.size}")

789

790

print("Top 5 Asks:")

791

for ask in btc_book.asks[:5]:

792

print(f" ${ask.price:.2f} x {ask.size}")

793

```

794

795

## Options Data

796

797

### OptionHistoricalDataClient Methods

798

799

```python { .api }

800

from alpaca.data.historical import OptionHistoricalDataClient

801

from alpaca.data.requests import (

802

OptionBarsRequest, OptionTradesRequest,

803

OptionLatestQuoteRequest, OptionLatestTradeRequest,

804

OptionSnapshotRequest, OptionChainRequest

805

)

806

807

options_client = OptionHistoricalDataClient(api_key="key", secret_key="secret")

808

809

# Options data methods

810

options_client.get_option_bars(OptionBarsRequest(...))

811

options_client.get_option_trades(OptionTradesRequest(...))

812

options_client.get_option_latest_quote(OptionLatestQuoteRequest(...))

813

options_client.get_option_latest_trade(OptionLatestTradeRequest(...))

814

options_client.get_option_snapshot(OptionSnapshotRequest(...))

815

816

# Options-specific: option chain data

817

options_client.get_option_chain(OptionChainRequest(...))

818

```

819

820

### Option Data Usage

821

822

```python { .api }

823

# Option symbols use OCC format: AAPL230317C00150000

824

# Format: [SYMBOL][YYMMDD][C/P][STRIKE_PRICE_PADDED]

825

826

# Get option bars

827

option_bars = options_client.get_option_bars(

828

OptionBarsRequest(

829

symbol_or_symbols="AAPL230317C00150000", # AAPL $150 Call expiring 3/17/23

830

timeframe=TimeFrame.Minute,

831

start=datetime.now() - timedelta(hours=6)

832

)

833

)

834

835

# Get option chain for underlying

836

option_chain = options_client.get_option_chain(

837

OptionChainRequest(

838

underlying_symbol="AAPL",

839

expiration_date=date(2023, 3, 17)

840

)

841

)

842

843

print("AAPL Option Chain 3/17/23:")

844

for contract in option_chain.options:

845

print(f"{contract.symbol}: ${contract.strike_price} {contract.type}")

846

```

847

848

## News Data

849

850

### News Client

851

852

```python { .api }

853

from alpaca.data.historical import NewsClient

854

from alpaca.data.requests import NewsRequest

855

856

news_client = NewsClient(api_key="key", secret_key="secret")

857

858

def get_news(self, request: NewsRequest) -> Union[NewsSet, RawData]:

859

"""

860

Get news articles with filtering.

861

862

Args:

863

request: News query parameters

864

865

Returns:

866

NewsSet: Collection of news articles

867

"""

868

```

869

870

### NewsRequest

871

872

```python { .api }

873

from alpaca.data.requests import NewsRequest

874

875

class NewsRequest(NonEmptyRequest):

876

def __init__(

877

self,

878

symbols: Optional[Union[str, List[str]]] = None, # Filter by symbols

879

start: Optional[datetime] = None, # Start time

880

end: Optional[datetime] = None, # End time

881

sort: Optional[Sort] = None, # Sort order

882

include_content: Optional[bool] = None, # Include article body

883

exclude_contentless: Optional[bool] = None, # Exclude articles without content

884

limit: Optional[int] = None # Max articles to return

885

):

886

```

887

888

### News Model

889

890

```python { .api }

891

from alpaca.data.models import News

892

893

class News:

894

"""News article information."""

895

896

id: str # Article ID

897

headline: str # Article headline

898

author: Optional[str] # Article author

899

created_at: datetime # Publication timestamp

900

updated_at: datetime # Last update timestamp

901

summary: Optional[str] # Article summary

902

content: Optional[str] # Full article content (if requested)

903

symbols: List[str] # Related symbols

904

url: Optional[str] # Source URL

905

images: Optional[List[dict]] # Article images

906

```

907

908

**Usage Examples:**

909

910

```python { .api }

911

# Get recent news for specific stocks

912

news = news_client.get_news(

913

NewsRequest(

914

symbols=["AAPL", "TSLA", "MSFT"],

915

start=datetime.now() - timedelta(hours=24),

916

limit=50,

917

include_content=True

918

)

919

)

920

921

print(f"Found {len(news.news)} articles")

922

for article in news.news[:5]:

923

print(f"\n{article.headline}")

924

print(f"Symbols: {', '.join(article.symbols)}")

925

print(f"Published: {article.created_at}")

926

if article.summary:

927

print(f"Summary: {article.summary[:200]}...")

928

929

# Get all market news (no symbol filter)

930

market_news = news_client.get_news(

931

NewsRequest(

932

start=datetime.now() - timedelta(hours=6),

933

sort=Sort.DESC,

934

limit=20

935

)

936

)

937

```

938

939

## Market Screening

940

941

### ScreenerClient

942

943

```python { .api }

944

from alpaca.data.historical import ScreenerClient

945

from alpaca.data.requests import MostActivesRequest, MarketMoversRequest

946

947

screener_client = ScreenerClient(api_key="key", secret_key="secret")

948

949

def get_most_actives(

950

self,

951

request: MostActivesRequest

952

) -> Union[MostActives, RawData]:

953

"""

954

Get most active stocks by volume or trade count.

955

956

Args:

957

request: Most actives query parameters

958

959

Returns:

960

MostActives: Most active stocks data

961

"""

962

963

def get_market_movers(

964

self,

965

request: MarketMoversRequest

966

) -> Union[Movers, RawData]:

967

"""

968

Get top gaining and losing stocks.

969

970

Args:

971

request: Market movers query parameters

972

973

Returns:

974

Movers: Top movers data with gainers and losers

975

"""

976

```

977

978

### Screener Request Classes

979

980

```python { .api }

981

from alpaca.data.requests import MostActivesRequest, MarketMoversRequest

982

from alpaca.data.enums import MostActivesBy, MarketType

983

984

class MostActivesRequest(NonEmptyRequest):

985

def __init__(

986

self,

987

by: MostActivesBy, # VOLUME or TRADE_COUNT

988

top: int, # Number of stocks to return (max 50)

989

market_type: Optional[MarketType] = None # STOCKS (default)

990

):

991

992

class MarketMoversRequest(NonEmptyRequest):

993

def __init__(

994

self,

995

top: int, # Number of gainers/losers (max 50)

996

market_type: Optional[MarketType] = None # STOCKS (default)

997

):

998

```

999

1000

**Usage Examples:**

1001

1002

```python { .api }

1003

from alpaca.data.enums import MostActivesBy

1004

1005

# Get most active stocks by volume

1006

most_active = screener_client.get_most_actives(

1007

MostActivesRequest(by=MostActivesBy.VOLUME, top=20)

1008

)

1009

1010

print("Most Active Stocks by Volume:")

1011

for stock in most_active.most_actives:

1012

print(f"{stock.symbol}: {stock.volume:,} shares, ${stock.price:.2f}")

1013

1014

# Get top movers (gainers and losers)

1015

movers = screener_client.get_market_movers(

1016

MarketMoversRequest(top=10)

1017

)

1018

1019

print("\nTop Gainers:")

1020

for gainer in movers.gainers:

1021

print(f"{gainer.symbol}: +{gainer.percent_change:.2f}% (${gainer.price:.2f})")

1022

1023

print("\nTop Losers:")

1024

for loser in movers.losers:

1025

print(f"{loser.symbol}: {loser.percent_change:.2f}% (${loser.price:.2f})")

1026

```

1027

1028

## Real-time Data Streaming

1029

1030

### Stock Data Stream

1031

1032

```python { .api }

1033

from alpaca.data.live import StockDataStream

1034

1035

class StockDataStream:

1036

def __init__(

1037

self,

1038

api_key: Optional[str] = None,

1039

secret_key: Optional[str] = None,

1040

raw_data: bool = False,

1041

feed: Optional[DataFeed] = None, # IEX, SIP, etc.

1042

websocket_params: Optional[dict] = None,

1043

url_override: Optional[str] = None

1044

):

1045

"""

1046

Initialize stock data stream for real-time data.

1047

1048

Args:

1049

api_key: API key for authentication

1050

secret_key: Secret key for authentication

1051

raw_data: Return raw data instead of models

1052

feed: Data feed selection

1053

websocket_params: WebSocket configuration

1054

url_override: Override WebSocket URL

1055

"""

1056

1057

def subscribe_bars(self, handler: Callable, *symbols) -> None:

1058

"""Subscribe to real-time bar updates."""

1059

1060

def subscribe_quotes(self, handler: Callable, *symbols) -> None:

1061

"""Subscribe to real-time quote updates."""

1062

1063

def subscribe_trades(self, handler: Callable, *symbols) -> None:

1064

"""Subscribe to real-time trade updates."""

1065

1066

def subscribe_updated_bars(self, handler: Callable, *symbols) -> None:

1067

"""Subscribe to minute bar updates."""

1068

1069

def subscribe_daily_bars(self, handler: Callable, *symbols) -> None:

1070

"""Subscribe to daily bar updates."""

1071

1072

def subscribe_statuses(self, handler: Callable, *symbols) -> None:

1073

"""Subscribe to trading status updates."""

1074

1075

def subscribe_lulds(self, handler: Callable, *symbols) -> None:

1076

"""Subscribe to limit up/limit down updates."""

1077

1078

def subscribe_corrections(self, handler: Callable, *symbols) -> None:

1079

"""Subscribe to trade corrections."""

1080

1081

def subscribe_cancellations(self, handler: Callable, *symbols) -> None:

1082

"""Subscribe to trade cancellations."""

1083

1084

async def run(self) -> None:

1085

"""Start the WebSocket connection and begin streaming."""

1086

```

1087

1088

### Real-time Data Example

1089

1090

```python { .api }

1091

import asyncio

1092

from alpaca.data.live import StockDataStream

1093

from alpaca.data.enums import DataFeed

1094

1095

# Initialize stream

1096

stream = StockDataStream(

1097

api_key="your-api-key",

1098

secret_key="your-secret-key",

1099

feed=DataFeed.IEX

1100

)

1101

1102

# Define data handlers

1103

async def trade_handler(data):

1104

"""Handle real-time trade data."""

1105

print(f"TRADE {data.symbol}: ${data.price} x {data.size} @ {data.timestamp}")

1106

1107

async def quote_handler(data):

1108

"""Handle real-time quote data."""

1109

spread = data.ask_price - data.bid_price

1110

print(f"QUOTE {data.symbol}: ${data.bid_price} x {data.ask_price} (${spread:.2f})")

1111

1112

async def bar_handler(data):

1113

"""Handle real-time bar data."""

1114

print(f"BAR {data.symbol}: O:${data.open} H:${data.high} L:${data.low} C:${data.close} V:{data.volume}")

1115

1116

# Subscribe to data streams

1117

symbols = ["AAPL", "TSLA", "SPY", "QQQ"]

1118

1119

stream.subscribe_trades(trade_handler, *symbols)

1120

stream.subscribe_quotes(quote_handler, *symbols)

1121

stream.subscribe_updated_bars(bar_handler, *symbols)

1122

1123

# Start streaming (this will run indefinitely)

1124

asyncio.run(stream.run())

1125

```

1126

1127

### Crypto Data Stream

1128

1129

```python { .api }

1130

from alpaca.data.live import CryptoDataStream

1131

1132

# Similar interface to stock stream but for crypto symbols

1133

crypto_stream = CryptoDataStream(

1134

api_key="your-api-key",

1135

secret_key="your-secret-key"

1136

)

1137

1138

# Subscribe to crypto data

1139

crypto_symbols = ["BTC/USD", "ETH/USD", "DOGE/USD"]

1140

crypto_stream.subscribe_trades(trade_handler, *crypto_symbols)

1141

crypto_stream.subscribe_quotes(quote_handler, *crypto_symbols)

1142

crypto_stream.subscribe_bars(bar_handler, *crypto_symbols)

1143

1144

# Crypto-specific: order book updates

1145

async def orderbook_handler(data):

1146

print(f"ORDERBOOK {data.symbol}: {len(data.bids)} bids, {len(data.asks)} asks")

1147

1148

crypto_stream.subscribe_orderbooks(orderbook_handler, "BTC/USD")

1149

```

1150

1151

### Option Data Stream

1152

1153

```python { .api }

1154

from alpaca.data.live import OptionDataStream

1155

1156

# Stream real-time options data

1157

option_stream = OptionDataStream(

1158

api_key="your-api-key",

1159

secret_key="your-secret-key"

1160

)

1161

1162

async def option_trade_handler(data):

1163

"""Handle real-time option trade data."""

1164

print(f"OPTION TRADE {data.symbol}: ${data.price} x {data.size}")

1165

1166

async def option_quote_handler(data):

1167

"""Handle real-time option quote data."""

1168

print(f"OPTION QUOTE {data.symbol}: ${data.bid_price} x ${data.ask_price}")

1169

1170

# Subscribe to option data

1171

option_symbols = ["AAPL230317C00150000", "TSLA230317P00200000"]

1172

option_stream.subscribe_trades(option_trade_handler, *option_symbols)

1173

option_stream.subscribe_quotes(option_quote_handler, *option_symbols)

1174

```

1175

1176

### News Data Stream

1177

1178

```python { .api }

1179

from alpaca.data.live import NewsDataStream

1180

1181

# Stream real-time news

1182

news_stream = NewsDataStream(

1183

api_key="your-api-key",

1184

secret_key="your-secret-key"

1185

)

1186

1187

async def news_handler(data):

1188

"""Handle real-time news."""

1189

print(f"NEWS: {data.headline}")

1190

print(f"Symbols: {', '.join(data.symbols)}")

1191

print(f"Time: {data.created_at}")

1192

1193

# Subscribe to news for specific symbols

1194

news_stream.subscribe_news(news_handler, "AAPL", "TSLA", "MSFT")

1195

1196

# Or subscribe to all news (no symbol filter)

1197

news_stream.subscribe_news(news_handler)

1198

```

1199

1200

## Advanced Streaming Example

1201

1202

```python { .api }

1203

import asyncio

1204

from datetime import datetime

1205

from collections import defaultdict

1206

from alpaca.data.live import StockDataStream, NewsDataStream

1207

from alpaca.data.enums import DataFeed

1208

1209

class RealTimeAnalyzer:

1210

def __init__(self, api_key: str, secret_key: str):

1211

# Initialize data streams

1212

self.data_stream = StockDataStream(

1213

api_key=api_key,

1214

secret_key=secret_key,

1215

feed=DataFeed.IEX

1216

)

1217

1218

self.news_stream = NewsDataStream(

1219

api_key=api_key,

1220

secret_key=secret_key

1221

)

1222

1223

# Data storage

1224

self.latest_prices = {}

1225

self.trade_volumes = defaultdict(int)

1226

self.price_alerts = {

1227

"AAPL": {"above": 180.00, "below": 170.00},

1228

"TSLA": {"above": 250.00, "below": 200.00}

1229

}

1230

1231

# Subscribe to streams

1232

self.setup_subscriptions()

1233

1234

def setup_subscriptions(self):

1235

"""Set up data stream subscriptions."""

1236

symbols = ["AAPL", "TSLA", "SPY", "QQQ", "MSFT"]

1237

1238

# Market data subscriptions

1239

self.data_stream.subscribe_trades(self.handle_trade, *symbols)

1240

self.data_stream.subscribe_quotes(self.handle_quote, *symbols)

1241

self.data_stream.subscribe_updated_bars(self.handle_bar, *symbols)

1242

1243

# News subscriptions

1244

self.news_stream.subscribe_news(self.handle_news, *symbols)

1245

1246

async def handle_trade(self, trade):

1247

"""Process real-time trade data."""

1248

symbol = trade.symbol

1249

self.latest_prices[symbol] = trade.price

1250

self.trade_volumes[symbol] += trade.size

1251

1252

# Check price alerts

1253

if symbol in self.price_alerts:

1254

alerts = self.price_alerts[symbol]

1255

if trade.price > alerts["above"]:

1256

print(f"šŸš€ {symbol} ABOVE ${alerts['above']}: ${trade.price}")

1257

elif trade.price < alerts["below"]:

1258

print(f"šŸ“‰ {symbol} BELOW ${alerts['below']}: ${trade.price}")

1259

1260

# Print large trades

1261

if trade.size >= 10000:

1262

print(f"šŸ‹ LARGE TRADE {symbol}: ${trade.price} x {trade.size:,}")

1263

1264

async def handle_quote(self, quote):

1265

"""Process real-time quote data."""

1266

spread = quote.ask_price - quote.bid_price

1267

spread_pct = (spread / quote.ask_price) * 100

1268

1269

# Alert on wide spreads

1270

if spread_pct > 0.5: # 0.5% spread

1271

print(f"āš ļø WIDE SPREAD {quote.symbol}: {spread_pct:.2f}%")

1272

1273

async def handle_bar(self, bar):

1274

"""Process real-time bar updates."""

1275

# Calculate intraday returns

1276

if bar.symbol in self.latest_prices:

1277

prev_price = self.latest_prices.get(f"{bar.symbol}_prev", bar.open)

1278

change_pct = ((bar.close - prev_price) / prev_price) * 100

1279

1280

if abs(change_pct) > 2.0: # 2% move

1281

direction = "UP" if change_pct > 0 else "DOWN"

1282

print(f"šŸ“Š {bar.symbol} {direction} {change_pct:+.2f}% - ${bar.close} (Vol: {bar.volume:,})")

1283

1284

self.latest_prices[f"{bar.symbol}_prev"] = bar.close

1285

1286

async def handle_news(self, news):

1287

"""Process real-time news."""

1288

print(f"šŸ“° NEWS: {news.headline}")

1289

print(f" Symbols: {', '.join(news.symbols)}")

1290

print(f" Time: {news.created_at}")

1291

1292

# Check for important keywords

1293

headline_lower = news.headline.lower()

1294

important_keywords = ["earnings", "merger", "acquisition", "fda approval", "bankruptcy"]

1295

1296

for keyword in important_keywords:

1297

if keyword in headline_lower:

1298

print(f"šŸ”„ IMPORTANT: {keyword.upper()} mentioned in news!")

1299

break

1300

1301

async def print_summary(self):

1302

"""Print periodic summary."""

1303

while True:

1304

await asyncio.sleep(60) # Every minute

1305

1306

print(f"\n=== MARKET SUMMARY ({datetime.now().strftime('%H:%M:%S')}) ===")

1307

for symbol, price in self.latest_prices.items():

1308

if not symbol.endswith("_prev"):

1309

volume = self.trade_volumes.get(symbol, 0)

1310

print(f"{symbol}: ${price:.2f} (Vol: {volume:,})")

1311

print("=" * 50)

1312

1313

async def run(self):

1314

"""Start the real-time analyzer."""

1315

print("šŸš€ Starting real-time market analyzer...")

1316

1317

# Start data streams

1318

data_task = asyncio.create_task(self.data_stream.run())

1319

news_task = asyncio.create_task(self.news_stream.run())

1320

summary_task = asyncio.create_task(self.print_summary())

1321

1322

try:

1323

# Run all tasks concurrently

1324

await asyncio.gather(data_task, news_task, summary_task)

1325

except KeyboardInterrupt:

1326

print("\nšŸ‘‹ Shutting down analyzer...")

1327

data_task.cancel()

1328

news_task.cancel()

1329

summary_task.cancel()

1330

1331

# Run the analyzer

1332

if __name__ == "__main__":

1333

analyzer = RealTimeAnalyzer(

1334

api_key="your-api-key",

1335

secret_key="your-secret-key"

1336

)

1337

1338

asyncio.run(analyzer.run())

1339

```

1340

1341

## Data Processing Utilities

1342

1343

### Converting to Pandas DataFrames

1344

1345

```python { .api }

1346

import pandas as pd

1347

1348

# BarSet, QuoteSet, TradeSet all have .df property

1349

bars = data_client.get_stock_bars(bars_request)

1350

df = bars.df

1351

1352

# DataFrame has MultiIndex: (timestamp, symbol)

1353

print(df.index.names) # ['timestamp', 'symbol']

1354

print(df.columns) # ['open', 'high', 'low', 'close', 'volume', ...]

1355

1356

# Access data for specific symbol

1357

aapl_data = df.xs('AAPL', level='symbol')

1358

print(aapl_data.tail())

1359

1360

# Pivot for time-series analysis

1361

pivot_df = df.reset_index().pivot(index='timestamp', columns='symbol', values='close')

1362

print(pivot_df.head())

1363

1364

# Calculate returns

1365

returns = pivot_df.pct_change().dropna()

1366

print(f"Correlations:\n{returns.corr()}")

1367

```

1368

1369

### Data Export and Storage

1370

1371

```python { .api }

1372

# Export to CSV

1373

bars_df = bars.df

1374

bars_df.to_csv('market_data.csv')

1375

1376

# Export to Parquet (more efficient for large datasets)

1377

bars_df.to_parquet('market_data.parquet')

1378

1379

# Store in database (example with SQLite)

1380

import sqlite3

1381

1382

conn = sqlite3.connect('market_data.db')

1383

bars_df.to_sql('stock_bars', conn, if_exists='append', index=True)

1384

conn.close()

1385

1386

# Export individual symbols

1387

for symbol in bars.symbols:

1388

symbol_bars = bars[symbol]

1389

symbol_df = pd.DataFrame([{

1390

'timestamp': bar.timestamp,

1391

'open': bar.open,

1392

'high': bar.high,

1393

'low': bar.low,

1394

'close': bar.close,

1395

'volume': bar.volume

1396

} for bar in symbol_bars])

1397

symbol_df.to_csv(f'{symbol}_bars.csv', index=False)

1398

```

1399

1400

## Common Types and Base Classes

1401

1402

### Base Request Types

1403

1404

```python { .api }

1405

from alpaca.common.requests import NonEmptyRequest

1406

from alpaca.common.enums import Sort, SupportedCurrencies

1407

1408

class NonEmptyRequest:

1409

"""Base class for API request objects with validation."""

1410

1411

class Sort(str, Enum):

1412

ASC = "asc" # Ascending order

1413

DESC = "desc" # Descending order

1414

1415

class SupportedCurrencies(str, Enum):

1416

USD = "USD" # US Dollar (default)

1417

GBP = "GBP" # British Pound

1418

CHF = "CHF" # Swiss Franc

1419

EUR = "EUR" # Euro

1420

CAD = "CAD" # Canadian Dollar

1421

```

1422

1423

## Error Handling and Rate Limits

1424

1425

```python { .api }

1426

from alpaca.common.exceptions import APIError

1427

import time

1428

1429

def robust_data_fetch(client, request, max_retries=3):

1430

"""Fetch data with error handling and retries."""

1431

1432

for attempt in range(max_retries):

1433

try:

1434

return client.get_stock_bars(request)

1435

1436

except APIError as e:

1437

if e.status_code == 429: # Rate limit

1438

wait_time = 2 ** attempt # Exponential backoff

1439

print(f"Rate limited, waiting {wait_time}s (attempt {attempt + 1})")

1440

time.sleep(wait_time)

1441

continue

1442

elif e.status_code == 422: # Invalid parameters

1443

print(f"Invalid request parameters: {e.message}")

1444

break

1445

else:

1446

print(f"API error: {e.message} (status: {e.status_code})")

1447

if attempt == max_retries - 1:

1448

raise

1449

time.sleep(1)

1450

except Exception as e:

1451

print(f"Unexpected error: {e}")

1452

if attempt == max_retries - 1:

1453

raise

1454

time.sleep(1)

1455

1456

return None

1457

1458

# Usage

1459

bars = robust_data_fetch(data_client, bars_request)

1460

if bars:

1461

print(f"Successfully retrieved {len(bars.df)} bars")

1462

else:

1463

print("Failed to retrieve data after all retries")

1464

```

1465

1466

## Complete Market Data Analysis Example

1467

1468

```python { .api }

1469

import pandas as pd

1470

import numpy as np

1471

from datetime import datetime, timedelta

1472

from alpaca.data.historical import StockHistoricalDataClient

1473

from alpaca.data.requests import StockBarsRequest, StockLatestQuoteRequest

1474

from alpaca.data.timeframe import TimeFrame

1475

from alpaca.data.enums import Adjustment

1476

1477

class MarketAnalyzer:

1478

def __init__(self, api_key: str, secret_key: str):

1479

self.client = StockHistoricalDataClient(api_key, secret_key)

1480

1481

def get_historical_data(self, symbols: list, days: int = 30) -> pd.DataFrame:

1482

"""Get historical daily data for analysis."""

1483

1484

request = StockBarsRequest(

1485

symbol_or_symbols=symbols,

1486

timeframe=TimeFrame.Day,

1487

start=datetime.now() - timedelta(days=days),

1488

adjustment=Adjustment.ALL

1489

)

1490

1491

bars = self.client.get_stock_bars(request)

1492

df = bars.df.reset_index()

1493

1494

# Pivot for analysis

1495

pivot_df = df.pivot(index='timestamp', columns='symbol', values='close')

1496

return pivot_df.fillna(method='forward')

1497

1498

def calculate_metrics(self, df: pd.DataFrame) -> dict:

1499

"""Calculate key financial metrics."""

1500

1501

# Daily returns

1502

returns = df.pct_change().dropna()

1503

1504

# Metrics calculation

1505

metrics = {}

1506

1507

for symbol in df.columns:

1508

symbol_returns = returns[symbol].dropna()

1509

1510

metrics[symbol] = {

1511

'total_return': (df[symbol].iloc[-1] / df[symbol].iloc[0] - 1) * 100,

1512

'volatility': symbol_returns.std() * np.sqrt(252) * 100, # Annualized

1513

'sharpe_ratio': (symbol_returns.mean() / symbol_returns.std()) * np.sqrt(252),

1514

'max_drawdown': self.calculate_max_drawdown(df[symbol]),

1515

'current_price': df[symbol].iloc[-1]

1516

}

1517

1518

return metrics

1519

1520

def calculate_max_drawdown(self, price_series: pd.Series) -> float:

1521

"""Calculate maximum drawdown."""

1522

peak = price_series.expanding().max()

1523

drawdown = (price_series - peak) / peak

1524

return drawdown.min() * 100

1525

1526

def get_correlation_matrix(self, df: pd.DataFrame) -> pd.DataFrame:

1527

"""Calculate correlation matrix."""

1528

returns = df.pct_change().dropna()

1529

return returns.corr()

1530

1531

def screen_stocks(self, symbols: list) -> pd.DataFrame:

1532

"""Screen stocks based on various criteria."""

1533

1534

# Get current quotes

1535

quotes = self.client.get_stock_latest_quote(

1536

StockLatestQuoteRequest(symbol_or_symbols=symbols)

1537

)

1538

1539

# Get historical data for calculations

1540

df = self.get_historical_data(symbols, days=90)

1541

metrics = self.calculate_metrics(df)

1542

1543

# Build screening results

1544

screening_data = []

1545

1546

for symbol in symbols:

1547

if symbol in quotes and symbol in metrics:

1548

quote = quotes[symbol]

1549

metric = metrics[symbol]

1550

1551

screening_data.append({

1552

'symbol': symbol,

1553

'price': metric['current_price'],

1554

'bid': quote.bid_price,

1555

'ask': quote.ask_price,

1556

'spread_pct': ((quote.ask_price - quote.bid_price) / quote.ask_price) * 100,

1557

'total_return_pct': metric['total_return'],

1558

'volatility_pct': metric['volatility'],

1559

'sharpe_ratio': metric['sharpe_ratio'],

1560

'max_drawdown_pct': metric['max_drawdown']

1561

})

1562

1563

return pd.DataFrame(screening_data).set_index('symbol')

1564

1565

def generate_report(self, symbols: list) -> None:

1566

"""Generate comprehensive market report."""

1567

1568

print("šŸ“Š MARKET ANALYSIS REPORT")

1569

print("=" * 50)

1570

1571

# Get data and metrics

1572

df = self.get_historical_data(symbols, days=60)

1573

metrics = self.calculate_metrics(df)

1574

correlation = self.get_correlation_matrix(df)

1575

screening = self.screen_stocks(symbols)

1576

1577

# Performance summary

1578

print("\nšŸ“ˆ PERFORMANCE SUMMARY (60 Days)")

1579

print("-" * 30)

1580

1581

perf_df = pd.DataFrame({

1582

symbol: {

1583

'Return %': f"{metrics[symbol]['total_return']:.2f}%",

1584

'Volatility %': f"{metrics[symbol]['volatility']:.2f}%",

1585

'Sharpe': f"{metrics[symbol]['sharpe_ratio']:.2f}",

1586

'Max DD %': f"{metrics[symbol]['max_drawdown']:.2f}%"

1587

} for symbol in symbols if symbol in metrics

1588

}).T

1589

1590

print(perf_df)

1591

1592

# Top performers

1593

print("\nšŸ† TOP PERFORMERS")

1594

print("-" * 20)

1595

1596

sorted_by_return = screening.sort_values('total_return_pct', ascending=False)

1597

print(sorted_by_return[['price', 'total_return_pct', 'volatility_pct']].head())

1598

1599

# Risk analysis

1600

print("\nāš ļø RISK ANALYSIS")

1601

print("-" * 15)

1602

1603

high_vol = screening[screening['volatility_pct'] > 30]

1604

if not high_vol.empty:

1605

print(f"High Volatility Stocks (>30%): {', '.join(high_vol.index)}")

1606

1607

wide_spreads = screening[screening['spread_pct'] > 0.5]

1608

if not wide_spreads.empty:

1609

print(f"Wide Spreads (>0.5%): {', '.join(wide_spreads.index)}")

1610

1611

# Correlation insights

1612

print("\nšŸ”— CORRELATION INSIGHTS")

1613

print("-" * 22)

1614

1615

# Find highest correlations (excluding self-correlation)

1616

corr_matrix = correlation.where(np.triu(np.ones(correlation.shape), k=1).astype(bool))

1617

high_corr = corr_matrix.stack().sort_values(ascending=False).head(3)

1618

1619

print("Highest Correlations:")

1620

for (stock1, stock2), corr_val in high_corr.items():

1621

print(f" {stock1} - {stock2}: {corr_val:.3f}")

1622

1623

# Investment recommendations

1624

print("\nšŸ’” INVESTMENT INSIGHTS")

1625

print("-" * 21)

1626

1627

# Best risk-adjusted returns

1628

best_sharpe = screening.nlargest(3, 'sharpe_ratio')

1629

print("Best Risk-Adjusted Returns (Sharpe Ratio):")

1630

for symbol, data in best_sharpe.iterrows():

1631

print(f" {symbol}: {data['sharpe_ratio']:.2f}")

1632

1633

# Momentum stocks

1634

momentum = screening[(screening['total_return_pct'] > 10) & (screening['volatility_pct'] < 40)]

1635

if not momentum.empty:

1636

print(f"\nMomentum Candidates: {', '.join(momentum.index)}")

1637

1638

print("\n" + "=" * 50)

1639

print(f"Report generated at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")

1640

1641

# Run comprehensive analysis

1642

if __name__ == "__main__":

1643

analyzer = MarketAnalyzer(

1644

api_key="your-api-key",

1645

secret_key="your-secret-key"

1646

)

1647

1648

# Analyze major tech stocks

1649

tech_stocks = ["AAPL", "MSFT", "GOOGL", "AMZN", "TSLA", "META", "NVDA", "NFLX"]

1650

1651

analyzer.generate_report(tech_stocks)

1652

```