Zero-config monitor and compare
- `trader.py monitor` — runs ALL 9 strategies by default, $10k capital, $2 fee, integer shares. Just start and forget. - `trader.py compare` — auto-discovers all state files in data/, no --strategy needed. Ranks by return with equity curves. - Monitor defaults: --capital 10000, --fixed-fee 2.0, --integer-shares Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
48
trader.py
48
trader.py
@@ -595,8 +595,31 @@ def cmd_status(args):
|
||||
|
||||
def cmd_compare(args):
|
||||
"""Compare multiple strategies side-by-side."""
|
||||
import glob as _glob
|
||||
|
||||
market = args.market
|
||||
strategy_names = args.strategy
|
||||
strategy_names = getattr(args, "strategy", None)
|
||||
|
||||
# Auto-discover: find all trader_{market}_*.json state files
|
||||
if not strategy_names:
|
||||
pattern = os.path.join("data", f"trader_{market}_*.json")
|
||||
files = sorted(_glob.glob(pattern))
|
||||
strategy_names = []
|
||||
for f in files:
|
||||
# Extract strategy name: trader_{market}_{name}.json
|
||||
base = os.path.basename(f) # trader_us_foo.json
|
||||
prefix = f"trader_{market}_"
|
||||
name = base[len(prefix):-len(".json")]
|
||||
# Skip sim_ prefixed (historical simulations) unless no live ones
|
||||
strategy_names.append(name)
|
||||
|
||||
if not strategy_names:
|
||||
print(f"No state files found for market '{market}' in data/.")
|
||||
print(f"Run 'monitor' or 'auto' first to generate state.")
|
||||
return
|
||||
|
||||
print(f" Auto-discovered {len(strategy_names)} strategies: "
|
||||
f"{', '.join(strategy_names)}")
|
||||
|
||||
# Load all states
|
||||
states = {}
|
||||
@@ -1277,19 +1300,19 @@ def main():
|
||||
|
||||
# Monitor (long-running daemon for tmux) — supports multiple strategies
|
||||
p_monitor = sub.add_parser("monitor",
|
||||
help="Long-running daemon: auto-runs daily after market close (for tmux)")
|
||||
help="Long-running daemon: runs ALL strategies daily (for tmux)")
|
||||
p_monitor.add_argument("--market", choices=UNIVERSES.keys(), default="us")
|
||||
p_monitor.add_argument("--strategy", nargs="+",
|
||||
choices=list(STRATEGY_REGISTRY.keys()),
|
||||
default=["recovery_mom_top10"],
|
||||
help="One or more strategies to run in parallel")
|
||||
p_monitor.add_argument("--capital", type=float, default=100_000)
|
||||
default=list(STRATEGY_REGISTRY.keys()),
|
||||
help="Strategies to run (default: ALL)")
|
||||
p_monitor.add_argument("--capital", type=float, default=10_000)
|
||||
p_monitor.add_argument("--tx-cost", type=float, default=0.001,
|
||||
help="Proportional transaction cost (default: 0.001 = 10bps)")
|
||||
p_monitor.add_argument("--fixed-fee", type=float, default=0.0,
|
||||
help="Fixed dollar fee per trade")
|
||||
p_monitor.add_argument("--integer-shares", action="store_true", default=False,
|
||||
help="Only trade whole shares (no fractional)")
|
||||
p_monitor.add_argument("--fixed-fee", type=float, default=2.0,
|
||||
help="Fixed dollar fee per trade (default: $2)")
|
||||
p_monitor.add_argument("--integer-shares", action="store_true", default=True,
|
||||
help="Only trade whole shares (default: True)")
|
||||
|
||||
# Status (strategy is a free-form string to allow sim_ prefixed names)
|
||||
p_status = sub.add_parser("status", help="Show current portfolio")
|
||||
@@ -1316,10 +1339,11 @@ def main():
|
||||
p_log.add_argument("--end", default=None, help="End date filter (YYYY-MM-DD)")
|
||||
|
||||
# Compare strategies
|
||||
p_cmp = sub.add_parser("compare", help="Compare multiple strategies side-by-side")
|
||||
p_cmp = sub.add_parser("compare",
|
||||
help="Compare strategies side-by-side (auto-discovers all if no --strategy)")
|
||||
p_cmp.add_argument("--market", choices=UNIVERSES.keys(), default="us")
|
||||
p_cmp.add_argument("--strategy", nargs="+", required=True,
|
||||
help="Strategy state names to compare (e.g. recovery_mom_top10 momentum)")
|
||||
p_cmp.add_argument("--strategy", nargs="+", default=None,
|
||||
help="Strategy names to compare (default: auto-discover all)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user