Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .github/workflows/auction-sheet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ name: auction-sheet
# closed at today's official open, today's ADR book is settled open -> close, and tonight's
# book is opened at today's official close - all in the sheet's "Auction book" and
# "Auction trades" tabs. Nothing is sent to Alpaca. The two crons cover ~16:25 New York in
# summer and winter time; the script itself only runs between 16:20 and midnight New York, once a day.
# summer and winter time; the script itself only runs between 16:50 and midnight New York (Yahoo's Asian bars, needed by
# the ADR book, are missing around 16:30-16:45), once a day.

on:
schedule:
Expand All @@ -14,7 +15,7 @@ on:
workflow_dispatch:
inputs:
force:
description: "run now even outside 16:20-24:00 New York"
description: "run now even outside 16:50-24:00 New York"
default: "false"

permissions:
Expand All @@ -27,7 +28,7 @@ concurrency:
jobs:
sleeve:
runs-on: ubuntu-latest
timeout-minutes: 40
timeout-minutes: 75
env:
ALPACA_API_KEY: ${{ secrets.ALPACA_API_KEY }} # market data only
ALPACA_SECRET_KEY: ${{ secrets.ALPACA_SECRET_KEY }}
Expand Down
2 changes: 1 addition & 1 deletion qtrade/clock.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class Job:
window_min=20),
Job("hft-shadow.yml", NY, ("09:26",), window_min=300), # its own chain then runs the session
Job("flip-sleeve.yml", NY, ("15:45",), window_min=400),
Job("auction-sheet.yml", NY, ("16:30",), window_min=400),
Job("auction-sheet.yml", NY, ("16:55",), window_min=400), # after Yahoo's ~16:30-16:45 refresh of Asian bars
Job("hoard-archive.yml", NY, ("16:45",), inputs=(("job", "eod"),), window_min=400),
Job("foreign-sheet.yml", "UTC", ("17:15", "23:30"), window_min=200), # 23:30: Asian bars Yahoo posted late
Job("hoard-archive.yml", "UTC", ("07:15",), weekdays=False, inputs=(("job", "archive"),), window_min=300),
Expand Down
5 changes: 5 additions & 0 deletions qtrade/intraday/adr_book.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ def home_moves(today: pd.Timestamp, tickers: list[str] | None = None) -> pd.Data
f = f[f.index.normalize() < day] # FX up to yesterday only
rows.append({"adr": t, "market": mkt, "home_ret": float(np.log(c.iloc[-1] / c.iloc[-2])),
"fx_ret_prev": float(f.iloc[-1]) if len(f) else np.nan})
if not rows: # say why, so an empty ADR book is never a mystery
sample = [h for h in homes if h in md.close][:4]
LOG.warning("ADR book: no home session dated %s; index ends %s; last bars %s", day.date(),
[str(d.date()) for d in md.close.index[-3:]],
{h: [str(d.date()) for d in md.close[h].dropna().index[-2:]] for h in sample})
return pd.DataFrame(rows)


Expand Down
8 changes: 4 additions & 4 deletions qtrade/intraday/auction_sheet.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

NY = "America/New_York"
TAB, TRADES_TAB = "Auction book", "Auction trades"
ADR_TRIES, ADR_RETRY_S = 4, 120
ADR_TRIES, ADR_RETRY_S = 10, 180 # Yahoo's Asian bars vanished ~16:30-16:40 NY (Nov 3-4), back by 16:50
LOG_HEADER = ["Date", "Overnight P&L $", "ADR P&L $", "Day P&L $", "Day %", "Equity $", "Overnight longs",
"Overnight shorts", "Overnight gross $", "ADR names", "Capital $"]
HOLD_HEADER = ["Symbol", "Shares", "Entry (official close)", "Position $"]
Expand Down Expand Up @@ -106,7 +106,7 @@ def day_inputs(cfg, tickers: list[str], signs: dict, day: pd.Timestamp) -> dict:
try:
moves = pd.DataFrame()
for attempt in range(ADR_TRIES): # Yahoo sometimes serves the Asian daily bars late
moves = home_moves(day, adr_names) # (2026-11-03: none at 21:31 UTC, 24 at 21:50)
moves = home_moves(day, adr_names) # (none at 16:31-16:38 NY on Nov 3-4, all back by 16:50)
LOG.info("ADR book: %d ADRs with a home session today (try %d)", len(moves), attempt + 1)
if len(moves) or day.weekday() >= 5:
break
Expand Down Expand Up @@ -252,11 +252,11 @@ def main(argv=None):
ap.add_argument("--tickers", default="data/auction_tickers.json")
ap.add_argument("--signs", default="data/auction_signs.json")
ap.add_argument("--dry-run", action="store_true")
ap.add_argument("--force", action="store_true", help="run outside 16:20-24:00 New York")
ap.add_argument("--force", action="store_true", help="run outside 16:50-24:00 New York")
args = ap.parse_args(argv)
setup_logging()
now = pd.Timestamp.now(tz=NY)
if not args.force and not (now.weekday() < 5 and 16 * 60 + 20 <= now.hour * 60 + now.minute < 24 * 60):
if not args.force and not (now.weekday() < 5 and 16 * 60 + 50 <= now.hour * 60 + now.minute < 24 * 60):
print({"skipped": f"outside the window ({now:%H:%M} NY)"})
return
sleeve = book_split().get("auction", 0.0)
Expand Down
Loading