polly-gamba 1.0.32 → 1.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/claude-trader.js +4 -1
- package/dist/position-monitor.js +26 -1
- package/package.json +1 -1
- package/service.log +1442 -0
- package/src/claude-trader.ts +5 -2
- package/src/lib/paper-trade.ts +1 -1
- package/src/mcp-server.ts +8 -5
- package/src/position-monitor.ts +26 -1
package/dist/claude-trader.js
CHANGED
|
@@ -311,8 +311,11 @@ CLOSE RULES — apply ALL that match, no thesis override allowed:
|
|
|
311
311
|
6. Position is UP >25% from entry AND has been held >48h — CLOSE to lock in profits. The market has moved significantly in your favor; gains are now vulnerable to reversion. Use take_profit reason. Exception: if the resolution event is within 7 days AND the position is still clearly on the right side, you may hold until resolution.
|
|
312
312
|
7. STALE POSITION: Position held >7 days AND price has moved <5% from entry AND resolution event is >30 days away — CLOSE to redeploy capital. A position that doesn't move over 7 days means the mispricing wasn't as large as estimated. Cut it, accept the small loss/gain, and redeploy to markets with active price movement.
|
|
313
313
|
8. CONCENTRATION VIOLATION: Count open positions by underlying theme (the single real-world event that resolves all of them). Examples: "Will Jesus return before GTA VI", "Will BTC hit $1M before GTA VI", "Will China invade Taiwan before GTA VI" all share the theme "GTA VI release date". Similarly "Will Spurs win NBA Finals", "Will OKC win NBA Finals", "Will Celtics win NBA Finals" all share the theme "2026 NBA Finals". If you have 3+ positions in the same theme, close the one with the smallest current edge (current price closest to 50/50 or furthest from your target) to reduce to 2 positions. Apply this BEFORE checking other rules.
|
|
314
|
+
9. SPORTSBOOK THESIS DECAY: If the original reasoning cited a sportsbook cross-reference (e.g. "sportsbooks imply X%, Polymarket shows Y%") AND the position is currently down >20%: estimate current sportsbook consensus from your world knowledge. If the original sportsbook-Polymarket gap has narrowed by >60% (e.g. original 15pp gap is now ≤6pp), the arbitrage thesis is exhausted — CLOSE with reason "thesis_decayed". Do not continue holding through hard stops when the original edge is structurally gone.
|
|
314
315
|
|
|
315
|
-
HOLD RULES: If NONE of the close rules apply and exit trigger NOT triggered, do nothing (no output needed)
|
|
316
|
+
HOLD RULES: If NONE of the close rules apply and exit trigger NOT triggered, do nothing (no output needed).
|
|
317
|
+
|
|
318
|
+
NOTE: Positions with no price data are automatically freed by the system after 24h (likely resolved or delisted). You will only receive positions with valid current prices.`;
|
|
316
319
|
const msg = JSON.stringify({
|
|
317
320
|
type: 'user',
|
|
318
321
|
message: { role: 'user', content: prompt }
|
package/dist/position-monitor.js
CHANGED
|
@@ -71,10 +71,18 @@ class PositionMonitor {
|
|
|
71
71
|
}
|
|
72
72
|
// Build review candidates with current price data for Claude
|
|
73
73
|
const reviewCandidates = [];
|
|
74
|
+
// Track positions with no price data that have been held >24h — likely resolved/delisted
|
|
75
|
+
const noPriceDataStale = [];
|
|
74
76
|
for (const pos of toCheck) {
|
|
75
77
|
const currentPrice = marketPriceCache.get(`${pos.market_id}|${pos.outcome}`) ?? null;
|
|
76
78
|
if (!currentPrice) {
|
|
77
|
-
|
|
79
|
+
const hoursHeld = (Date.now() - pos.ts) / (1000 * 60 * 60);
|
|
80
|
+
if (hoursHeld >= 24) {
|
|
81
|
+
noPriceDataStale.push(pos);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
console.warn(`[position-monitor] WARNING: no price data for ${pos.market_id} ${pos.outcome} — skipping review (market may be resolved or delisted)`);
|
|
85
|
+
}
|
|
78
86
|
continue;
|
|
79
87
|
}
|
|
80
88
|
const entryPrice = pos.price;
|
|
@@ -99,6 +107,23 @@ class PositionMonitor {
|
|
|
99
107
|
});
|
|
100
108
|
}
|
|
101
109
|
}
|
|
110
|
+
// Close positions with no price data held >24h — market is likely resolved or delisted
|
|
111
|
+
for (const pos of noPriceDataStale) {
|
|
112
|
+
const posKey = `${pos.market_id}_${pos.outcome}_${pos.ts}`;
|
|
113
|
+
const alreadyClosed = await this.redis.sismember(`${this.prefix}:closed_ids`, posKey);
|
|
114
|
+
if (alreadyClosed)
|
|
115
|
+
continue;
|
|
116
|
+
const closed = { ...pos, status: 'closed', exit_price: pos.price, pnl: 0, closed_at: Date.now(), reason: 'market_unavailable' };
|
|
117
|
+
await this.redis.sadd(`${this.prefix}:closed_ids`, posKey);
|
|
118
|
+
await this.redis.lpush(`${this.prefix}:closed_positions`, JSON.stringify(closed));
|
|
119
|
+
await this.redis.ltrim(`${this.prefix}:closed_positions`, 0, 9999);
|
|
120
|
+
await this.redis.lpush(`${this.prefix}:log`, JSON.stringify({ type: 'position_closed', data: closed, ts: Date.now(), trigger: 'market_unavailable' }));
|
|
121
|
+
await this.redis.ltrim(`${this.prefix}:log`, 0, 9999);
|
|
122
|
+
console.log(`[position-monitor] CLOSED [market_unavailable] "${String(pos.market_question).slice(0, 50)}" ${pos.outcome} — no price data for >24h, freeing capital`);
|
|
123
|
+
}
|
|
124
|
+
if (noPriceDataStale.length > 0) {
|
|
125
|
+
console.log(`[position-monitor] freed ${noPriceDataStale.length} stale no-price-data positions`);
|
|
126
|
+
}
|
|
102
127
|
// Execute programmatic hard stops BEFORE sending to Claude
|
|
103
128
|
// These are deterministic rules — no judgment needed
|
|
104
129
|
const hardStopClosed = [];
|