WS0 cleanup: DuckDB-free + wire DATABASE_URL
- Drop duckdb dependency (pyproject, requirements) -> psycopg2-binary. - run_live_paper: boot log shows the real Postgres target (masked); add _db_target_desc() helper. - .env.example: document DATABASE_URL / PG* vars; mark WATCHER_EVENT_DB_PATH legacy. - evaluation/storage.py: INSERT OR REPLACE -> INSERT (setup_id is a fresh uuid). Verified: 67/67 tests green on Postgres with duckdb UNINSTALLED; app boots against the live endpoint (127.0.0.1:5432 proxy) and wrote 205 daily bars. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
c4669fe0ce
commit
b1ef0930ca
5 files changed
+32
-5
No files matched your search
+11
-1
@@ -2,6 +2,16 @@
|
||||
# Momentum — environment configuration (copy to .env and fill)
|
||||
# ============================================================
|
||||
|
||||
# ---- Database (PostgreSQL) — the single datastore (event store + bar warehouse)
|
||||
# Either a full URL:
|
||||
DATABASE_URL=postgresql://USER:PASSWORD@HOST:5432/momentum
|
||||
# ...or individual vars (used only if DATABASE_URL is unset):
|
||||
# PGHOST=127.0.0.1
|
||||
# PGPORT=5432
|
||||
# PGUSER=admin
|
||||
# PGPASSWORD=
|
||||
# PGDATABASE=momentum
|
||||
|
||||
# ---- Alpaca (market data + paper broker) — REQUIRED for live paper trading
|
||||
ALPACA_API_KEY=
|
||||
ALPACA_SECRET_KEY=
|
||||
@@ -47,7 +57,7 @@ TRADING_MAX_DAILY_LOSS_PCT=0.03 # daily-loss circuit breaker
|
||||
# Intraday watcher (signal engine)
|
||||
WATCHER_ENABLED=1
|
||||
WATCHER_INTERVAL_SECONDS=60
|
||||
WATCHER_EVENT_DB_PATH=./data/momentum.duckdb
|
||||
# WATCHER_EVENT_DB_PATH is legacy and ignored — the datastore is PostgreSQL (see DATABASE_URL above)
|
||||
WATCHER_MAX_SYMBOLS=25
|
||||
WATCHER_MIN_BARS=30
|
||||
WATCHER_MIN_QUALITY=0.30
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ version = "0.4.0"
|
||||
description = "Small-cap momentum research & paper-trading system"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = [
|
||||
"duckdb>=1.0.0",
|
||||
"psycopg2-binary>=2.9.0",
|
||||
"pandas>=2.0.0",
|
||||
"pydantic>=2.0.0",
|
||||
"pydantic-settings>=2.0.0",
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
duckdb>=1.0.0
|
||||
psycopg2-binary>=2.9.0
|
||||
pandas>=2.0.0
|
||||
pydantic>=2.0.0
|
||||
pytest>=7.0.0
|
||||
|
||||
+18
-1
@@ -65,6 +65,23 @@ def _now_session_date():
|
||||
return session_date
|
||||
|
||||
|
||||
def _db_target_desc() -> str:
|
||||
"""Human-readable Postgres target for the boot log (password masked)."""
|
||||
url = os.environ.get("DATABASE_URL")
|
||||
if url:
|
||||
if "://" in url and "@" in url:
|
||||
scheme, rest = url.split("://", 1)
|
||||
creds, host = rest.split("@", 1)
|
||||
user = creds.split(":", 1)[0]
|
||||
return f"{scheme}://{user}:***@{host}"
|
||||
return url
|
||||
host = os.environ.get("PGHOST", "localhost")
|
||||
port = os.environ.get("PGPORT", "5432")
|
||||
db = os.environ.get("PGDATABASE", "momentum")
|
||||
user = os.environ.get("PGUSER", "")
|
||||
return f"postgresql://{user}@{host}:{port}/{db}"
|
||||
|
||||
|
||||
def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(description="Momentum live paper-trading loop")
|
||||
parser.add_argument("--once", action="store_true", help="run one pass and exit")
|
||||
@@ -188,7 +205,7 @@ def main(argv: list[str] | None = None) -> int:
|
||||
symbols: list[str] = rt["symbols"]
|
||||
client = rt["client"]
|
||||
|
||||
print(f"[boot] session={rt['session_id']} event_db={rt['event_db']}")
|
||||
print(f"[boot] session={rt['session_id']} db={_db_target_desc()}")
|
||||
print(f"[boot] watching: {', '.join(symbols)}")
|
||||
if not rt["has_keys"]:
|
||||
print("[boot] no ALPACA_API_KEY/SECRET — dry mode: ingestion, sync and "
|
||||
|
||||
@@ -13,7 +13,7 @@ def store_setup_event(con, symbol: str, session_date, result: dict) -> str:
|
||||
best = setups[0] if setups else {}
|
||||
con.execute(
|
||||
"""
|
||||
INSERT OR REPLACE INTO setup_events
|
||||
INSERT INTO setup_events
|
||||
(setup_id, symbol, setup_time, session_date, setup_name,
|
||||
entry_reference_price, invalidation_price, gap_pct, relative_volume)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
|
||||
Reference in new issue
Block a user