mirror of
https://github.com/jaxperro/winning-wallet-finder.git
synced 2026-07-27 15:57:47 +00:00
band-guarded mirror exits (#21 successor): mirror sells >=90c only, sub-band sells ignored+ledgered; sell-band study slice; backtest parity
Sell-band evidence: every band <90c LOSES by mirroring (<30c +$79/sell given up, 50-70c +$7.29); >=90c SAVES (-$0.85/sell, n=68). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,21 +5,28 @@
|
||||
"bankroll_pct": 0.04,
|
||||
"price_guard_abs": 0.05,
|
||||
"fak_retry_s": 10,
|
||||
"fak_retry_niche_s": {"crypto": 4, "esports": 10, "sports": 25,
|
||||
"geo": 25, "politics": 25, "other": 25},
|
||||
"fak_retry_niche_s": {
|
||||
"crypto": 4,
|
||||
"esports": 10,
|
||||
"sports": 25,
|
||||
"geo": 25,
|
||||
"politics": 25,
|
||||
"other": 25
|
||||
},
|
||||
"taker_fee_rate": 0.03,
|
||||
"discord_webhook": "",
|
||||
"follow": {
|
||||
"buy_only": true,
|
||||
"entry_mode": "maker",
|
||||
"exit_mode": "hold",
|
||||
"exit_mode": "mirror",
|
||||
"min_their_usd": 25.0,
|
||||
"min_entry": 0.0,
|
||||
"max_entry": 0.95,
|
||||
"class_pct": {
|
||||
"volume": 0.04,
|
||||
"whale": 0.12
|
||||
}
|
||||
},
|
||||
"mirror_sell_min_p": 0.9
|
||||
},
|
||||
"risk": {
|
||||
"max_trade_usd": 1000000.0,
|
||||
|
||||
@@ -732,6 +732,29 @@ class CopyTrader:
|
||||
price = self._live_price(token, "sell")
|
||||
if price is None:
|
||||
return
|
||||
# band-guarded mirroring (2026-07-23, #21 successor): the sell-band
|
||||
# study (research/sell_mirror_study.py) showed mirrored exits LOSE
|
||||
# in every band below 90c (exits gave up value; <30c +$79/sell left
|
||||
# on the table) and SAVE money at >=90c (near-resolution
|
||||
# profit-taking, n=68 -$0.85/sell). Sells below the floor are
|
||||
# ignored-and-ledgered exactly like hold mode, so the
|
||||
# counterfactual stream keeps accruing.
|
||||
min_p = (self.cfg.get("follow") or {}).get("mirror_sell_min_p", 0.0)
|
||||
if price < min_p:
|
||||
self.log(f"EXIT {label} — BAND-SKIP (sell {price:.2f} < "
|
||||
f"{min_p:.2f} floor, their frac {frac:.2f})")
|
||||
if self.on_ignored_exit:
|
||||
self.on_ignored_exit({
|
||||
"ts": round(time.time(), 1), "token": str(token),
|
||||
"their_size": their_size, "their_prev": their_prev,
|
||||
"frac": round(frac, 4), "reason": "band",
|
||||
"sell_px": round(price, 4),
|
||||
"shares_held": round(mine.get("shares", 0), 4),
|
||||
"cost_held": round(mine.get("cost", 0), 2),
|
||||
"title": (mine.get("title") or "")[:80],
|
||||
"outcome": mine.get("outcome"),
|
||||
"wallet": mine.get("wallet", "")})
|
||||
return
|
||||
if any(po.get("token") == token
|
||||
for po in self.state.get("pending_orders", [])):
|
||||
self.log(f"EXIT {label} — skip (in-play hold already pending on "
|
||||
|
||||
@@ -49,14 +49,15 @@
|
||||
"follow": {
|
||||
"buy_only": true,
|
||||
"entry_mode": "maker",
|
||||
"exit_mode": "hold",
|
||||
"exit_mode": "mirror",
|
||||
"min_their_usd": 25.0,
|
||||
"min_entry": 0.0,
|
||||
"max_entry": 0.95,
|
||||
"class_pct": {
|
||||
"volume": 0.04,
|
||||
"whale": 0.12
|
||||
}
|
||||
},
|
||||
"mirror_sell_min_p": 0.9
|
||||
},
|
||||
"risk": {
|
||||
"max_trade_usd": 1000000.0,
|
||||
|
||||
+16
-4
@@ -148,6 +148,17 @@ except Exception:
|
||||
_FOLLOW = {}
|
||||
ENTRY_MODE = os.environ.get("BT_ENTRY_MODE", _FOLLOW.get("entry_mode", "taker"))
|
||||
EXIT_MODE = os.environ.get("BT_EXIT_MODE", _FOLLOW.get("exit_mode", "mirror"))
|
||||
# band-guarded mirroring (#21 successor): sells below this price are NOT
|
||||
# mirrored — held to truth like hold mode (sell-band study: every band
|
||||
# <90c lost by mirroring; >=90c saved). 0.0 = mirror everything.
|
||||
MIRROR_SELL_MIN_P = float(os.environ.get(
|
||||
"BT_MIRROR_SELL_MIN_P", _FOLLOW.get("mirror_sell_min_p", 0.0)))
|
||||
|
||||
|
||||
def _mirrors(exit_p):
|
||||
"""Would the bot mirror a sell at this price under the current flags?"""
|
||||
return (EXIT_MODE != "hold"
|
||||
and (exit_p or 0) >= MIRROR_SELL_MIN_P)
|
||||
|
||||
|
||||
def entry_model(p, stake):
|
||||
@@ -525,7 +536,7 @@ def main():
|
||||
cash -= cost; fees_paid += fee; perW[b["wallet"]]["bets"] += 1
|
||||
shares = stake / p_eff # lag-adjusted entry price
|
||||
if b["kind"] == "res":
|
||||
if b.get("exit_t") and EXIT_MODE != "hold":
|
||||
if b.get("exit_t") and _mirrors(b.get("exit_p")):
|
||||
# the signal SOLD pre-resolution -> mirror the exit, like the
|
||||
# live bot: their exit price with the slippage haircut against
|
||||
# us, minus the taker fee (sells pay it; redeems don't)
|
||||
@@ -581,7 +592,7 @@ def main():
|
||||
stake = m.get("stake") or STAKE_MIN
|
||||
p_eff, fee, cost = entry_model(m["p"], stake)
|
||||
shares = stake / p_eff
|
||||
if m.get("exit_t") and EXIT_MODE != "hold": # would have mirrored
|
||||
if m.get("exit_t") and _mirrors(m.get("exit_p")): # would have mirrored
|
||||
xp = max(0.001, m["exit_p"] * (1 - SLIP))
|
||||
return shares * xp - shares * FEE_RATE * xp * (1 - xp) - cost
|
||||
if m.get("wp") is not None or m.get("won") is not None:
|
||||
@@ -600,12 +611,12 @@ def main():
|
||||
return m.get("won")
|
||||
|
||||
def _missed_won(m):
|
||||
if m.get("exit_t") and EXIT_MODE != "hold":
|
||||
if m.get("exit_t") and _mirrors(m.get("exit_p")):
|
||||
return None # mirrored exit: truth is the price
|
||||
return _truth_won(m)
|
||||
|
||||
def _missed_status(m):
|
||||
if m.get("exit_t") and EXIT_MODE != "hold":
|
||||
if m.get("exit_t") and _mirrors(m.get("exit_p")):
|
||||
return "sold"
|
||||
w = _truth_won(m)
|
||||
if w is None:
|
||||
@@ -683,6 +694,7 @@ def main():
|
||||
for m in missed[:60]],
|
||||
"missed_pnl": round(sum(hypo_pnl(m) for m in missed), 2),
|
||||
"entry_mode": ENTRY_MODE, "exit_mode": EXIT_MODE,
|
||||
"mirror_sell_min_p": MIRROR_SELL_MIN_P,
|
||||
}
|
||||
json.dump(out, open(os.path.join(HERE, OUT) if not os.path.isabs(OUT) else OUT, "w"),
|
||||
separators=(",", ":"))
|
||||
|
||||
@@ -37,6 +37,28 @@ def main():
|
||||
db = tape.connect()
|
||||
tape.build_resolved(db)
|
||||
pays = fwd.payouts_for(db, [str(s["token"]) for s in sells])
|
||||
# sell-price band slice: WHERE is mirroring unprofitable? delta>0 = the
|
||||
# exit gave up value (holding won); delta<0 = the exit saved us.
|
||||
BANDS = [(0, .30, "<30c"), (.30, .50, "30-50c"), (.50, .70, "50-70c"),
|
||||
(.70, .90, "70-90c"), (.90, 1.01, ">=90c")]
|
||||
print("\n== SELL-PRICE BANDS (both books pooled, chain-graded) ==")
|
||||
for lo, hi, tag in BANDS:
|
||||
bn = bd = 0
|
||||
for s2 in sells:
|
||||
p2 = pays.get(str(s2["token"]))
|
||||
if p2 is None or p2 == 0.5:
|
||||
continue
|
||||
sp = s2.get("price") or 0
|
||||
if not (lo <= sp < hi):
|
||||
continue
|
||||
sh2 = s2.get("shares") or 0
|
||||
bn += 1
|
||||
bd += (p2 - sp) * sh2
|
||||
if bn:
|
||||
lbl = ("SKIP-MIRROR (exits gave up value)" if bd > 0
|
||||
else "mirror OK (exits saved money)")
|
||||
print(f" {tag:>7}: n={bn:>3} · net delta {bd:+8.2f} "
|
||||
f"(${bd/bn:+.2f}/sell) -> {lbl}")
|
||||
for book in ("live", "paper"):
|
||||
ss = [s for s in sells if s["_book"] == book]
|
||||
n = unk = refund = right = wrong = 0
|
||||
|
||||
Reference in New Issue
Block a user