polymarket-bot-testing / capital_manager.py
frank0957's picture
Update capital_manager.py
4fa9b12 verified
Raw
History Blame Contribute Delete
6.03 kB
# capital_manager.py
# Four‑tier compounding engine + dynamic risk pool + circuit breaker.
# Now supports virtual mode (reads/writes an independent state file).
# All comments in English.
import os
import json
import time
from datetime import datetime, timezone
# ── File paths ──────────────────────────────────────────
STATE_FILE = "/app/capital_state.json"
ORIGINAL_DEPOSIT_FILE = "/app/original_deposit.json"
BALANCE_FILE = "/app/balance.txt"
VIRTUAL_STATE_FILE = "/app/virtual_capital_state.json"
# ── Defaults ────────────────────────────────────────────
DEFAULT_RISK_POOL = 5.0
DEFAULT_TOTAL_CAPITAL = 20.0
HALT_FILE = "/app/halt_trading.txt"
UNHALT_FILE = "/app/unhalt_trading.txt"
# ── Compounding tiers ───────────────────────────────────
TIERS = [
(0.25, 10, "L1"),
(0.50, 20, "L2"),
(0.75, 30, "L3"),
(0.90, 70, "L4"),
]
def read_json(path, default=None):
try:
if os.path.exists(path):
with open(path, "r") as f:
return json.load(f)
except:
pass
return default
def write_json(path, data):
try:
with open(path, "w") as f:
json.dump(data, f, indent=2)
except Exception as e:
print(f"[Capital] Failed to write {path}: {e}", flush=True)
def read_file(path, default=""):
try:
if os.path.exists(path):
with open(path, "r") as f:
return f.read().strip()
except:
pass
return default
def load_state(filepath=STATE_FILE):
state = read_json(filepath)
if state is None:
state = {
"tier_index": 0,
"consecutive_wins": 0,
"consecutive_losses": 0,
"risk_pool": DEFAULT_RISK_POOL,
"total_capital": DEFAULT_TOTAL_CAPITAL,
"max_bet": DEFAULT_RISK_POOL * 0.20,
"reinvest_rate": TIERS[0][0],
"halted": False,
"original_deposit": None,
"deposit_date": None,
}
return state
def save_state(state, filepath=STATE_FILE):
write_json(filepath, state)
def get_risk_ratio(total_capital):
if total_capital <= 50:
return 0.25
elif total_capital <= 200:
return 0.20
elif total_capital <= 1000:
return 0.15
elif total_capital <= 5000:
return 0.10
else:
return 0.08
def update_after_trade(won: bool, profit_amount: float, filepath=STATE_FILE):
state = load_state(filepath)
if state["original_deposit"] is None and filepath != VIRTUAL_STATE_FILE:
bal = read_file(BALANCE_FILE, "0")
try:
bal = float(bal)
except:
bal = 0.0
if bal > 0:
state["original_deposit"] = bal
state["deposit_date"] = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC")
state["total_capital"] += profit_amount
if won:
state["consecutive_wins"] += 1
state["consecutive_losses"] = 0
tier_idx = state["tier_index"]
required = TIERS[tier_idx][1]
if state["consecutive_wins"] >= required and tier_idx < len(TIERS) - 1:
state["tier_index"] = tier_idx + 1
state["consecutive_wins"] = 0
state["reinvest_rate"] = TIERS[state["tier_index"]][0]
print(f"[Capital] 🟢 Upgraded to {TIERS[state['tier_index']][2]} "
f"({state['reinvest_rate']:.0%} reinvest)", flush=True)
reinvest = profit_amount * state["reinvest_rate"]
state["risk_pool"] += reinvest
else:
state["consecutive_losses"] += 1
state["consecutive_wins"] = 0
state["risk_pool"] = max(0.0, state["risk_pool"] + profit_amount)
if state["consecutive_losses"] >= 2 and state["tier_index"] > 0:
state["tier_index"] -= 1
state["consecutive_wins"] = 0
state["consecutive_losses"] = 0
state["reinvest_rate"] = TIERS[state["tier_index"]][0]
print(f"[Capital] 🔴 Downgraded to {TIERS[state['tier_index']][2]} "
f"({state['reinvest_rate']:.0%} reinvest)", flush=True)
total = state["total_capital"]
ratio = get_risk_ratio(total)
target_risk_pool = total * ratio
if target_risk_pool > state["risk_pool"]:
state["risk_pool"] = target_risk_pool
elif state["risk_pool"] > target_risk_pool:
state["risk_pool"] = target_risk_pool
initial_risk = state["original_deposit"] * 0.25 if state["original_deposit"] else DEFAULT_RISK_POOL
if state["risk_pool"] < initial_risk * 0.5:
state["halted"] = True
print("[Capital] ⚠️ CIRCUIT BREAKER TRIGGERED: risk pool < 50% of initial", flush=True)
if os.path.exists(HALT_FILE):
state["halted"] = True
os.remove(HALT_FILE)
print("[Capital] ⚠️ Manual HALT triggered", flush=True)
if os.path.exists(UNHALT_FILE):
state["halted"] = False
os.remove(UNHALT_FILE)
print("[Capital] ✅ Manual UNHALT — trading resumed", flush=True)
state["max_bet"] = round(state["risk_pool"] * 0.20, 2)
save_state(state, filepath)
return state
def get_summary():
state = load_state()
tier = TIERS[state["tier_index"]]
return {
"tier": tier[2],
"tier_index": state["tier_index"],
"reinvest_rate": state["reinvest_rate"],
"consecutive_wins": state["consecutive_wins"],
"wins_needed": tier[1],
"consecutive_losses": state["consecutive_losses"],
"risk_pool": round(state["risk_pool"], 2),
"max_bet": round(state["max_bet"], 2),
"total_capital": round(state["total_capital"], 2),
"halted": state["halted"],
"original_deposit": state["original_deposit"],
"deposit_date": state["deposit_date"],
}