Files
trading-bot/src/trading_bot/data/fetch_alpaca_daily.py
T
2026-08-11 20:13:41 +03:00

108 lines
3.0 KiB
Python

"""Alpaca daily candle fetcher CLI wrapper.
The reusable implementation lives in the shared library module so the same
fetching and parquet persistence logic can be reused by the prediction flow.
"""
from __future__ import annotations
import argparse
import os
from pathlib import Path
from trading_bot.data.alpaca_daily_lib import (
DEFAULT_DURATION,
DEFAULT_OUTPUT_DIR,
DailyCandle,
candles_to_frame,
current_market_date,
default_end_date,
duration_to_start_date,
fetch_daily_candles,
oldest_stored_date_or_today,
parse_duration,
parse_end_date,
print_candles,
read_existing_candles,
write_candles,
)
def parse_args() -> argparse.Namespace:
"""Parse command line arguments."""
parser = argparse.ArgumentParser(description="Fetch daily Alpaca candles.")
parser.add_argument("symbol", help="Ticker symbol to fetch, such as SPY.")
end_date_group = parser.add_mutually_exclusive_group()
end_date_group.add_argument(
"--end-date",
type=parse_end_date,
help="Request end date in YYYYMMDD format. Defaults to yesterday.",
)
end_date_group.add_argument(
"--end-date-from-parquet",
action="store_true",
help=(
"Use the oldest date from the symbol Parquet file as the request "
"end date. Defaults to today if the file is missing or empty."
),
)
parser.add_argument(
"--duration",
type=parse_duration,
default=DEFAULT_DURATION,
help=(
"Duration string, such as '1 W', '1 M', or '1 Y'. "
f"Defaults to {DEFAULT_DURATION}."
),
)
parser.add_argument(
"--output-dir",
type=Path,
default=DEFAULT_OUTPUT_DIR,
help=f"Directory for Parquet files. Defaults to {DEFAULT_OUTPUT_DIR}.",
)
parser.add_argument(
"--api-key",
default=os.getenv("ALPACA_API_KEY"),
help="Alpaca API Key ID (defaults to ALPACA_API_KEY env var or .env).",
)
parser.add_argument(
"--secret-key",
default=os.getenv("ALPACA_SECRET_KEY"),
help="Alpaca Secret Key (defaults to ALPACA_SECRET_KEY env var or .env).",
)
return parser.parse_args()
def main() -> None:
"""Run the daily candle fetcher."""
args = parse_args()
symbol = args.symbol.upper()
output_path = args.output_dir / f"{symbol}.parquet"
end_date = (
oldest_stored_date_or_today(output_path)
if args.end_date_from_parquet
else args.end_date or default_end_date()
)
print(
f"Fetching {symbol} daily candles ending {end_date:%Y-%m-%d} "
f"for duration {args.duration} via Alpaca API"
)
candles = fetch_daily_candles(
symbol,
end_date,
args.duration,
api_key=args.api_key,
secret_key=args.secret_key,
)
print(f"Fetched {len(candles)} daily candles for {symbol}.")
stored = write_candles(output_path, symbol, candles)
print(f"Wrote {len(stored)} total daily rows to {output_path}")
if __name__ == "__main__":
main()