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):
|
def cmd_compare(args):
|
||||||
"""Compare multiple strategies side-by-side."""
|
"""Compare multiple strategies side-by-side."""
|
||||||
|
import glob as _glob
|
||||||
|
|
||||||
market = args.market
|
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
|
# Load all states
|
||||||
states = {}
|
states = {}
|
||||||
@@ -1277,19 +1300,19 @@ def main():
|
|||||||
|
|
||||||
# Monitor (long-running daemon for tmux) — supports multiple strategies
|
# Monitor (long-running daemon for tmux) — supports multiple strategies
|
||||||
p_monitor = sub.add_parser("monitor",
|
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("--market", choices=UNIVERSES.keys(), default="us")
|
||||||
p_monitor.add_argument("--strategy", nargs="+",
|
p_monitor.add_argument("--strategy", nargs="+",
|
||||||
choices=list(STRATEGY_REGISTRY.keys()),
|
choices=list(STRATEGY_REGISTRY.keys()),
|
||||||
default=["recovery_mom_top10"],
|
default=list(STRATEGY_REGISTRY.keys()),
|
||||||
help="One or more strategies to run in parallel")
|
help="Strategies to run (default: ALL)")
|
||||||
p_monitor.add_argument("--capital", type=float, default=100_000)
|
p_monitor.add_argument("--capital", type=float, default=10_000)
|
||||||
p_monitor.add_argument("--tx-cost", type=float, default=0.001,
|
p_monitor.add_argument("--tx-cost", type=float, default=0.001,
|
||||||
help="Proportional transaction cost (default: 0.001 = 10bps)")
|
help="Proportional transaction cost (default: 0.001 = 10bps)")
|
||||||
p_monitor.add_argument("--fixed-fee", type=float, default=0.0,
|
p_monitor.add_argument("--fixed-fee", type=float, default=2.0,
|
||||||
help="Fixed dollar fee per trade")
|
help="Fixed dollar fee per trade (default: $2)")
|
||||||
p_monitor.add_argument("--integer-shares", action="store_true", default=False,
|
p_monitor.add_argument("--integer-shares", action="store_true", default=True,
|
||||||
help="Only trade whole shares (no fractional)")
|
help="Only trade whole shares (default: True)")
|
||||||
|
|
||||||
# Status (strategy is a free-form string to allow sim_ prefixed names)
|
# Status (strategy is a free-form string to allow sim_ prefixed names)
|
||||||
p_status = sub.add_parser("status", help="Show current portfolio")
|
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)")
|
p_log.add_argument("--end", default=None, help="End date filter (YYYY-MM-DD)")
|
||||||
|
|
||||||
# Compare strategies
|
# 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("--market", choices=UNIVERSES.keys(), default="us")
|
||||||
p_cmp.add_argument("--strategy", nargs="+", required=True,
|
p_cmp.add_argument("--strategy", nargs="+", default=None,
|
||||||
help="Strategy state names to compare (e.g. recovery_mom_top10 momentum)")
|
help="Strategy names to compare (default: auto-discover all)")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user