108 lines
3.0 KiB
Python
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()
|