"""quant_swarm.py -Launch and run the full swarm."""
import os
import time
import threading
from horizon.fund import FundCluster, StrategyConfig
import horizon as hz
from swarm_factory import create_agent
from swarm_blocks import PIPELINE_TEMPLATES
# ============================================================
# Configuration
# ============================================================
TOTAL_CAPITAL = 500_000
WEBHOOK = os.environ.get("SWARM_WEBHOOK_URL", "")
# Capital allocation across agents
AGENT_ALLOCATIONS = {
"crypto_hunter": 0.25, # $125k, crypto prediction markets
"politics_scanner": 0.20, # $100k, political event markets
"sports_edge": 0.15, # $75k, sports outcome markets
"macro_rates": 0.15, # $75k, macro/rates/treasury
"cross_exchange": 0.10, # $50k, cross-exchange arbitrage
"tail_risk": 0.10, # $50k, tail / low-probability events
"high_frequency": 0.05, # $25k, short-lived opportunities
}
# ============================================================
# Create the agents
# ============================================================
agents = {}
# Agent 1: Crypto markets -Polymarket + Coinbase feeds
agents["crypto_hunter"] = create_agent(
name="crypto_hunter",
capital=TOTAL_CAPITAL * AGENT_ALLOCATIONS["crypto_hunter"],
exchanges=[
hz.Polymarket(
private_key=os.environ.get("POLYMARKET_PRIVATE_KEY", ""),
api_key=os.environ.get("POLYMARKET_API_KEY"),
api_secret=os.environ.get("POLYMARKET_API_SECRET"),
api_passphrase=os.environ.get("POLYMARKET_API_PASSPHRASE"),
),
],
drawdown_pct=20.0,
alert_webhook=WEBHOOK,
)
# Agent 2: Political event markets -Polymarket + Kalshi
agents["politics_scanner"] = create_agent(
name="politics_scanner",
capital=TOTAL_CAPITAL * AGENT_ALLOCATIONS["politics_scanner"],
exchanges=[
hz.Polymarket(
private_key=os.environ.get("POLYMARKET_PRIVATE_KEY", ""),
api_key=os.environ.get("POLYMARKET_API_KEY"),
api_secret=os.environ.get("POLYMARKET_API_SECRET"),
api_passphrase=os.environ.get("POLYMARKET_API_PASSPHRASE"),
),
hz.Kalshi(api_key=os.environ.get("KALSHI_API_KEY", "")),
],
drawdown_pct=12.0,
alert_webhook=WEBHOOK,
)
# Agent 3: Sports outcome markets -Kalshi
agents["sports_edge"] = create_agent(
name="sports_edge",
capital=TOTAL_CAPITAL * AGENT_ALLOCATIONS["sports_edge"],
exchanges=[
hz.Kalshi(api_key=os.environ.get("KALSHI_API_KEY", "")),
],
drawdown_pct=15.0,
alert_webhook=WEBHOOK,
)
# Agent 4: Macro/rates -Kalshi + IBKR for ForecastEx
agents["macro_rates"] = create_agent(
name="macro_rates",
capital=TOTAL_CAPITAL * AGENT_ALLOCATIONS["macro_rates"],
exchanges=[
hz.Kalshi(api_key=os.environ.get("KALSHI_API_KEY", "")),
hz.IBKR(
host=os.environ.get("IBKR_HOST", "localhost"),
port=int(os.environ.get("IBKR_PORT", "5000")),
),
],
drawdown_pct=10.0, # tighter limits on macro
alert_webhook=WEBHOOK,
)
# Agent 5: Cross-exchange arbitrage, all exchanges
agents["cross_exchange"] = create_agent(
name="cross_exchange",
capital=TOTAL_CAPITAL * AGENT_ALLOCATIONS["cross_exchange"],
exchanges=[
hz.Polymarket(
private_key=os.environ.get("POLYMARKET_PRIVATE_KEY", ""),
api_key=os.environ.get("POLYMARKET_API_KEY"),
api_secret=os.environ.get("POLYMARKET_API_SECRET"),
api_passphrase=os.environ.get("POLYMARKET_API_PASSPHRASE"),
),
hz.Kalshi(api_key=os.environ.get("KALSHI_API_KEY", "")),
],
drawdown_pct=8.0, # arb should have low drawdown
rebalance_secs=30.0, # faster cycle for arb
alert_webhook=WEBHOOK,
)
# Agent 6: Tail risk / low-probability events
agents["tail_risk"] = create_agent(
name="tail_risk",
capital=TOTAL_CAPITAL * AGENT_ALLOCATIONS["tail_risk"],
exchanges=[
hz.Polymarket(
private_key=os.environ.get("POLYMARKET_PRIVATE_KEY", ""),
api_key=os.environ.get("POLYMARKET_API_KEY"),
api_secret=os.environ.get("POLYMARKET_API_SECRET"),
api_passphrase=os.environ.get("POLYMARKET_API_PASSPHRASE"),
),
],
drawdown_pct=30.0, # loose limits, tail bets are volatile
alert_webhook=WEBHOOK,
)
# Agent 7: High-frequency short-lived opportunities
agents["high_frequency"] = create_agent(
name="high_frequency",
capital=TOTAL_CAPITAL * AGENT_ALLOCATIONS["high_frequency"],
exchanges=[
hz.Polymarket(
private_key=os.environ.get("POLYMARKET_PRIVATE_KEY", ""),
api_key=os.environ.get("POLYMARKET_API_KEY"),
api_secret=os.environ.get("POLYMARKET_API_SECRET"),
api_passphrase=os.environ.get("POLYMARKET_API_PASSPHRASE"),
),
],
drawdown_pct=15.0,
rebalance_secs=15.0, # fastest cycle
alert_webhook=WEBHOOK,
)
# ============================================================
# Seed each agent with initial strategy templates
# ============================================================
# Each agent gets a few pipeline templates to start with.
# The autonomous loop will discover markets, backtest, and deploy on its own.
# These seeds just give each agent a starting point.
def seed_agent(agent: FundManager, domain: str, templates: list[str], markets: list[str]):
"""Give an agent initial strategies to explore. All start in paper mode."""
for template_name in templates:
pipeline = PIPELINE_TEMPLATES.get(template_name)
if not pipeline:
continue
for market in markets:
agent.add_strategy(StrategyConfig(
name=f"{domain}_{template_name}_{market}",
pipeline=pipeline,
markets=[market],
mode="paper", # always start paper, promotion manager handles the rest
))
# Crypto agent: scan BTC, ETH, SOL prediction markets
seed_agent(agents["crypto_hunter"], "crypto",
["ensemble_mm", "momentum_directional"],
["btc-above-100k", "eth-above-5k"])
# Politics agent: scan election and policy markets
seed_agent(agents["politics_scanner"], "politics",
["mean_reversion_mm", "oracle_directional"],
["will-x-win-2028", "will-y-pass"])
# Sports agent: scan game outcome markets
seed_agent(agents["sports_edge"], "sports",
["mean_reversion_mm", "mr_directional"],
["nba-finals-winner", "superbowl-2027"])
# Macro agent: rates and economic indicators
seed_agent(agents["macro_rates"], "macro",
["oracle_mm", "momentum_directional"],
["fed-rate-cut-june", "cpi-above-3-pct"])
# Arb agent: look for cross-exchange mispricings
seed_agent(agents["cross_exchange"], "arb",
["ensemble_mm"],
["btc-above-100k", "will-x-win-2028"])
# Tail risk: cheap options on unlikely events
seed_agent(agents["tail_risk"], "tail",
["mr_directional"],
["major-earthquake-2027"])
# HF agent: fast markets with tight spreads
seed_agent(agents["high_frequency"], "hf",
["momentum_mm", "mean_reversion_mm"],
["btc-above-100k"])
# ============================================================
# Wire into FundCluster
# ============================================================
cluster = FundCluster()
for name, agent in agents.items():
cluster.add_fund(name, agent)
# ============================================================
# Launch the swarm
# ============================================================
print("=" * 60)
print(" QUANT SWARM - Launching agents")
print("=" * 60)
print(f" Total capital: ${TOTAL_CAPITAL:,.0f}")
print(f" Agents: {len(agents)}")
print()
for name, alloc in AGENT_ALLOCATIONS.items():
capital = TOTAL_CAPITAL * alloc
print(f" {name:20s} ${capital:>10,.0f} ({alloc:.0%})")
print()
print(" Starting all agents...")
cluster.start_all()
print(" All agents running. Oversight loops active.")
print("=" * 60)
# ============================================================
# Central monitoring loop
# ============================================================
def monitor_swarm(cluster: FundCluster, interval: float = 60.0):
"""
Central monitoring thread. Prints aggregate status and
rebalances capital if any agent drifts too far from target.
"""
while True:
try:
status = cluster.aggregate_status()
risk = cluster.aggregate_risk()
print(f"\n{'─' * 60}")
print(f" SWARM STATUS | NAV: ${status['total_nav']:,.0f}")
print(f" Weighted Drawdown: {risk['weighted_avg_drawdown_pct']:.1f}%")
print(f" Max Single Agent: {risk['max_drawdown_fund']} "
f"({risk['max_single_fund_drawdown_pct']:.1f}%)")
print(f"{'─' * 60}")
for name, fund_status in status["funds"].items():
nav = fund_status["nav"]
dd = fund_status["drawdown_pct"]
strats = fund_status.get("running_strategies", 0)
ks = fund_status.get("kill_switch", False)
flag = " KILL SWITCH" if ks else ""
print(f" {name:20s} NAV=${nav:>10,.0f} DD={dd:5.1f}% "
f"strategies={strats}{flag}")
# Check if any agent needs rebalancing (>20% drift from target)
total_nav = status["total_nav"]
if total_nav > 0:
for name, target_pct in AGENT_ALLOCATIONS.items():
if name not in status["funds"]:
continue
actual_pct = status["funds"][name]["nav"] / total_nav
drift = abs(actual_pct - target_pct)
if drift > 0.20 * target_pct:
print(f" ** {name} drifted {drift:.1%} from target -"
f"consider rebalancing")
time.sleep(interval)
except Exception as e:
print(f" Monitor error: {e}")
time.sleep(interval)
# Run monitor in background
monitor_thread = threading.Thread(
target=monitor_swarm,
args=(cluster, 60.0),
daemon=True,
)
monitor_thread.start()
# Main thread keeps running
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
print("\nShutting down swarm...")
cluster.stop_all()
print("All agents stopped.")