diff --git a/archive/copytrade.py b/archive/copytrade.py index 8f6c0a2f..1bc0f0e9 100644 --- a/archive/copytrade.py +++ b/archive/copytrade.py @@ -267,36 +267,42 @@ class CopyTrader: DD_THRESHOLD = 0.80 # below 80% of the high-water mark… DD_FACTOR = 0.5 # …bet half size until equity recovers - def stake_mult(self, wallet=None): - """Per-wallet stake multiplier from follow.stake_mult ({address: mult}) — - lets high-conviction wallets bet a larger equity fraction (e.g. 3.0 turns - a 4% book into 12% for that wallet). Defaults to 1.""" - mults = (self.cfg.get("follow") or {}).get("stake_mult") or {} - return float(mults.get((wallet or "").lower(), 1.0)) + def wallet_class(self, wallet=None): + """'volume' (default) or 'whale', from follow.wallet_class ({address: class}).""" + classes = (self.cfg.get("follow") or {}).get("wallet_class") or {} + return classes.get((wallet or "").lower(), "volume") + + def stake_frac(self, wallet=None): + """Equity fraction for this wallet's signals, by class: + follow.class_pct maps class -> fraction (e.g. volume 0.04, whale 0.12). + A class missing from class_pct falls back to bankroll_pct.""" + pcts = (self.cfg.get("follow") or {}).get("class_pct") or {} + pct = pcts.get(self.wallet_class(wallet)) + return self.cfg["bankroll_pct"] if pct is None else float(pct) def stake_usd(self, wallet=None): - """Next bet size = bankroll_pct × current WORKING equity (cash + open cost - basis), so stakes compound with the book in both directions; halved while - in a >20% drawdown from the high-water mark. Falls back to the flat static - stake when cash isn't tracked (legacy poll CLI). A per-wallet - follow.stake_mult scales the fraction for that wallet's signals (the - sweep threshold below stays on the BASE fraction so which wallet happens - to trade doesn't change when profits get banked). + """Next bet size = the wallet's class fraction (stake_frac) × current + WORKING equity (cash + open cost basis), so stakes compound with the book + in both directions; halved while in a >20% drawdown from the high-water + mark. Falls back to the flat static stake when cash isn't tracked + (legacy poll CLI). The sweep threshold below stays on the BASE + bankroll_pct so which wallet happens to trade doesn't change when + profits get banked. stake_cap_usd (profit ratchet): once working equity exceeds cap/bankroll_pct — the level where stakes hit the cap — the surplus CASH is swept into state["reserve"]: banked, never bet, immune to drawdowns. Stakes stay pinned ~at the cap, where marketable fills are still inside typical book depth.""" - mult = self.stake_mult(wallet) + frac = self.stake_frac(wallet) cash = self.state.get("cash") if cash is None: - return self.cfg["bankroll_usd"] * self.cfg["bankroll_pct"] * mult - frac = self.cfg["bankroll_pct"] + return self.cfg["bankroll_usd"] * frac + base = self.cfg["bankroll_pct"] cap = self.cfg.get("stake_cap_usd") or 0 eq = cash + self.open_exposure() - if cap and frac > 0 and eq > cap / frac: - sweep = min(cash, eq - cap / frac) + if cap and base > 0 and eq > cap / base: + sweep = min(cash, eq - cap / base) if sweep > 0: self.state["cash"] = cash = cash - sweep self.state["reserve"] = self.state.get("reserve", 0.0) + sweep @@ -305,7 +311,7 @@ class CopyTrader: self.state["hwm"] = hwm if eq < self.DD_THRESHOLD * hwm: frac *= self.DD_FACTOR - stake = frac * eq * mult + stake = frac * eq return min(stake, cap) if cap else stake def record_miss(self, wallet, token, cond, title, outcome, price, want, reason): diff --git a/live/copybot.paper.json b/live/copybot.paper.json index f2877308..0e573131 100644 --- a/live/copybot.paper.json +++ b/live/copybot.paper.json @@ -62,9 +62,13 @@ }, "min_entry": 0.0, "max_entry": 0.95, - "stake_mult": { - "0xf5fe759cece500f58a431ef8dacea321f6e3e23d": 3.0, - "0x73afc8160c17830c0c7281a7bf570c871455b880": 3.0 + "wallet_class": { + "0xf5fe759cece500f58a431ef8dacea321f6e3e23d": "whale", + "0x73afc8160c17830c0c7281a7bf570c871455b880": "whale" + }, + "class_pct": { + "volume": 0.04, + "whale": 0.12 } }, "risk": {