Skip to content

Commit 090cd34

Browse files
committed
fix(polymarket): correct NO-side Kelly sizing + gate live orders on owner address
Two correctness fixes flagged by Codex review on PR #57. P1 — polymarketAutonomy.ts NO-side sizing: estimateSizeForRiskBudget() expects the win probability of the *purchased* token, but the autonomy loop was always passing `best.fairValueEstimate` which is the YES probability. For `best.side === "no"` candidates that reverses Kelly: a contrarian NO on a 93% YES market got sized as if NO had ~80% win probability, producing wildly oversized live orders. Flip the probability for NO before sizing. P2 — polymarketAuth.ts placement gate: When POLYMARKET_OWNER_ADDRESS is unset, syncPolymarketPositions() silently no-ops. Live orders still went through, but the exit monitor never saw the resulting positions — no auto-close, no trailing stop, no drift-close. Block live placement until the env var is set. Failing closed beats trading positions we can't reconcile. https://claude.ai/code/session_01To82bdNQsUtCeAyGJFLQc3
1 parent ee95d47 commit 090cd34

2 files changed

Lines changed: 24 additions & 1 deletion

File tree

server/_core/polymarketAuth.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,22 @@ export async function placePolymarketOrder(
213213
error: "Polymarket wallet private key + funder address required for order signing",
214214
};
215215
}
216+
// Gate live placement on POLYMARKET_OWNER_ADDRESS being set. Without it,
217+
// syncPolymarketPositions() silently no-ops, so newly opened live positions
218+
// are invisible to the exit monitor (no auto-close, no trailing stop, no
219+
// drift-close detection). Failing closed here is safer than placing an
220+
// order we can't reconcile.
221+
if (!ENV.polymarketOwnerAddress) {
222+
return {
223+
success: false,
224+
error:
225+
"POLYMARKET_OWNER_ADDRESS is not set — live placement blocked. " +
226+
"Without the EOA proxy address, position-sync cannot reconcile new " +
227+
"positions and the exit monitor would never see them. Set the " +
228+
"env var to your Polymarket wallet address (the 0x... shown on " +
229+
"your account page) and redeploy.",
230+
};
231+
}
216232
try {
217233
const { buildPolymarketClobClient, submitSignedPolymarketOrder } = await import(
218234
"./polymarketSigner"

server/_core/polymarketAutonomy.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -616,9 +616,16 @@ export async function runPolymarketAutonomousTrading(
616616
bankroll
617617
);
618618

619+
// estimateSizeForRiskBudget expects the win probability of the *purchased*
620+
// token, not the YES probability. For NO trades the signal's
621+
// fairValueEstimate is still the YES probability, so flip it before
622+
// sizing — otherwise a contrarian NO on a 93% YES market gets sized as
623+
// if NO has ~80% win probability and the live order is wildly oversized.
624+
const purchasedTokenProb =
625+
best.side === "no" ? 1 - best.fairValueEstimate : best.fairValueEstimate;
619626
const rawSize = estimateSizeForRiskBudget(
620627
bankroll,
621-
best.fairValueEstimate,
628+
purchasedTokenProb,
622629
best.limitPrice,
623630
MAX_POLYMARKET_ORDER_USDC,
624631
0.25

0 commit comments

Comments
 (0)