polly-gamba 1.0.41 → 1.0.42

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.
@@ -212,6 +212,7 @@ ${m.description ? `- Description: ${m.description.slice(0, 200)}` : ''}`).join('
212
212
  - Correlation examples: "Will Jesus return before GTA VI", "Will BTC hit $1M before GTA VI", "Will China invade Taiwan before GTA VI" — all three resolve based on GTA VI's release date. They are the SAME theme.
213
213
  - Similarly: "Will Orbán be PM" and "Will Magyar be PM" are both the Hungary 2026 election — treat as same theme (you may hold both as a hedge pair, but do not add a third Hungary position).
214
214
  - IMPORTANT: All 2028 US election markets share one theme — "2028 US election". This includes: Dem primary nominees (Newsom, Harris, etc.), Rep primary nominees (Vance, Rubio, etc.), and the general election winner. Do NOT hold more than 2 positions across this entire cycle.
215
+ - IMPORTANT: All Russia-Ukraine conflict markets share one theme — "Russia-Ukraine conflict". This includes: Putin removal, Zelenskyy removal, ceasefire timing, territorial outcomes, and any other market that resolves based on the Russia-Ukraine war's trajectory. Do NOT hold more than 2 positions across this entire theme.
215
216
  - If you're uncertain whether a market correlates to an existing theme, assume it does and skip.
216
217
 
217
218
  ## CLOSED MARKET DISCIPLINE (absolute rule — never override):
@@ -310,13 +311,13 @@ ${positionLines}
310
311
 
311
312
  CLOSE RULES — apply ALL that match, no thesis override allowed:
312
313
  1. Exit trigger condition has been met (e.g. specific price level hit, event occurred). Apply literally.
313
- 2. Position is down >35% AND the fundamental thesis has materially weakened or been disproven (market structure changed, key assumption invalidated).
314
+ 2. Position is down >35% HARD CLOSE. This is a programmatic rule enforced server-side; by the time you see this position it may already be closed. Do NOT override with thesis defense.
314
315
  3. Your side of the position is priced below 10% — HARD CLOSE. The market has strongly repriced against you. Do NOT override this with "thesis not disproven yet." At <10%, expected value of holding is near zero.
315
316
  4. Position is down >50% — HARD CLOSE regardless of thesis. Cut losses. No exceptions.
316
317
  5. You have 2+ open positions in the SAME market with the SAME outcome — close the NEWER entry (higher ts value) regardless of P&L. Duplicate same-outcome positions double exposure without incremental edge. Keep the original entry.
317
318
  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.
318
319
  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.
319
- 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". IMPORTANT: All positions tied to the 2028 US election cycle share one theme — "2028 US election". This includes: 2028 Dem primary nominees (Newsom, etc.), 2028 Rep primary nominees (Vance, Rubio, etc.), and the 2028 general election winner — regardless of which stage of the race resolves each market. If you have 3+ positions in the same theme: close positions one by one (starting with the one whose current price is closest to 50/50) until you have ≤2 in that theme. If you have 4, you must close 2. If you have 5, close 3. Do NOT stop after closing just one if the theme still has 3+ positions. Apply this BEFORE checking other rules. This check requires the FULL position list — which is why Step 0 mandates calling get_positions first.
320
+ 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". IMPORTANT: All positions tied to the 2028 US election cycle share one theme — "2028 US election". This includes: 2028 Dem primary nominees (Newsom, etc.), 2028 Rep primary nominees (Vance, Rubio, etc.), and the 2028 general election winner — regardless of which stage of the race resolves each market. IMPORTANT: All Russia-Ukraine conflict positions share one theme — "Russia-Ukraine conflict". This includes: Putin removal/survival, Zelenskyy removal/survival, ceasefire timing, territorial outcomes — any market that resolves based on how the Russia-Ukraine war progresses. If you have 3+ positions in the same theme: close positions one by one (starting with the one whose current price is closest to 50/50) until you have ≤2 in that theme. If you have 4, you must close 2. If you have 5, close 3. Do NOT stop after closing just one if the theme still has 3+ positions. Apply this BEFORE checking other rules. This check requires the FULL position list — which is why Step 0 mandates calling get_positions first.
320
321
  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%: CLOSE immediately with reason "thesis_decayed". This is a mechanical rule — a -20% drawdown on a sportsbook arb trade is itself the signal that the cross-market gap has closed or the thesis was wrong. Do NOT attempt to re-estimate current sportsbook consensus or override based on "the sportsbook line is still there." The drawdown is the verdict. No exceptions.
321
322
 
322
323
  HOLD RULES: If NONE of the close rules apply and exit trigger NOT triggered, do nothing (no output needed).
@@ -144,9 +144,9 @@ class PositionMonitor {
144
144
  const hardStopClosed = [];
145
145
  for (const candidate of reviewCandidates) {
146
146
  const isPriceBelowFloor = candidate.current_price <= 0.10;
147
- const isLargeEnoughLoss = candidate.gain_pct <= -0.50;
147
+ const isLargeEnoughLoss = candidate.gain_pct <= -0.35;
148
148
  if (isPriceBelowFloor || isLargeEnoughLoss) {
149
- await this.executeHardStop(candidate, isPriceBelowFloor ? 'price_below_floor' : 'stop_loss_50pct');
149
+ await this.executeHardStop(candidate, isPriceBelowFloor ? 'price_below_floor' : 'stop_loss_35pct');
150
150
  hardStopClosed.push(candidate.market_id);
151
151
  }
152
152
  }
@@ -257,15 +257,15 @@ async function runHardStopTests() {
257
257
  const isPriceBelowFloor = price <= 0.10;
258
258
  assert(isPriceBelowFloor, 'price=0.08 should trigger floor stop');
259
259
  });
260
- await test('F2: loss = -50% triggers stop-loss', async () => {
261
- const gain = -0.50;
262
- const isLargeEnoughLoss = gain <= -0.50;
263
- assert(isLargeEnoughLoss, 'exactly -50% should trigger stop-loss');
260
+ await test('F2: loss = -35% triggers stop-loss', async () => {
261
+ const gain = -0.35;
262
+ const isLargeEnoughLoss = gain <= -0.35;
263
+ assert(isLargeEnoughLoss, 'exactly -35% should trigger stop-loss');
264
264
  });
265
- await test('F3: loss = -49.9% does NOT trigger stop-loss', async () => {
266
- const gain = -0.499;
267
- const isLargeEnoughLoss = gain <= -0.50;
268
- assert(!isLargeEnoughLoss, '-49.9% should NOT trigger stop-loss');
265
+ await test('F3: loss = -34.9% does NOT trigger stop-loss', async () => {
266
+ const gain = -0.349;
267
+ const isLargeEnoughLoss = gain <= -0.35;
268
+ assert(!isLargeEnoughLoss, '-34.9% should NOT trigger stop-loss');
269
269
  });
270
270
  await test('F4: price = 0.10 triggers floor (boundary — off-by-one vs stated rule)', async () => {
271
271
  // Code uses <= 0.10 but the Claude prompt rule says "priced below 10%"
@@ -275,12 +275,12 @@ async function runHardStopTests() {
275
275
  assert(isPriceBelowFloor, 'price=0.10 triggers stop (code behavior)');
276
276
  console.log('\n [NOTE] Boundary: price=0.10 triggers hard stop. Prompt says "<10%" but code uses "<=0.10".');
277
277
  });
278
- await test('F5: price > 0.10 and loss < 50% — no hard stop', async () => {
278
+ await test('F5: price > 0.10 and loss < 35% — no hard stop', async () => {
279
279
  const price = 0.12;
280
- const gain = -0.40;
280
+ const gain = -0.30;
281
281
  const isPriceBelowFloor = price <= 0.10;
282
- const isLargeEnoughLoss = gain <= -0.50;
283
- assert(!isPriceBelowFloor && !isLargeEnoughLoss, 'price=0.12, -40% should not trigger hard stop');
282
+ const isLargeEnoughLoss = gain <= -0.35;
283
+ assert(!isPriceBelowFloor && !isLargeEnoughLoss, 'price=0.12, -30% should not trigger hard stop');
284
284
  });
285
285
  }
286
286
  // ─── G) Double-Close Bug ─────────────────────────────────────────────────────
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polly-gamba",
3
- "version": "1.0.41",
3
+ "version": "1.0.42",
4
4
  "description": "Coinbase price signal → Claude brain → Polymarket CLOB execution",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
package/service.log CHANGED
@@ -4723,3 +4723,306 @@ npm warn deprecated prebuild-install@7.1.3: No longer maintained. Please contact
4723
4723
  [expiring] fetching expiring markets (closing within 72h, vol24h>$10k, liq>$10k, price 0.05-0.95)
4724
4724
  [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4725
4725
  [scan] failed to fetch markets: fetch failed
4726
+ [position-monitor] WARNING: no price data for 558934 YES — missing 0.3h (closes after 24h continuous)
4727
+ [position-monitor] WARNING: no price data for 566140 NO — missing 0.3h (closes after 24h continuous)
4728
+ [position-monitor] WARNING: no price data for 540819 NO — missing 0.3h (closes after 24h continuous)
4729
+ [position-monitor] WARNING: no price data for 568629 YES — first miss recorded, watching (market may be resolved or delisted)
4730
+ [position-monitor] WARNING: no price data for 558936 YES — first miss recorded, watching (market may be resolved or delisted)
4731
+ [position-monitor] WARNING: no price data for 553866 NO — first miss recorded, watching (market may be resolved or delisted)
4732
+ [position-monitor] WARNING: no price data for 567689 NO — first miss recorded, watching (market may be resolved or delisted)
4733
+ [position-monitor] WARNING: no price data for 566142 NO — first miss recorded, watching (market may be resolved or delisted)
4734
+ [position-monitor] WARNING: no price data for 540844 NO — first miss recorded, watching (market may be resolved or delisted)
4735
+ [position-monitor] WARNING: no price data for 562828 NO — first miss recorded, watching (market may be resolved or delisted)
4736
+ [position-monitor] WARNING: no price data for 566188 NO — first miss recorded, watching (market may be resolved or delisted)
4737
+ [position-monitor] WARNING: no price data for 559651 NO — first miss recorded, watching (market may be resolved or delisted)
4738
+ [position-monitor] WARNING: no price data for 567621 NO — first miss recorded, watching (market may be resolved or delisted)
4739
+ [position-monitor] checked=22 review_candidates=5 hard_stops=0 (moved>5% or <72h expiry)
4740
+ [gamma] Loaded 498 markets (filtered from 500)
4741
+ [expiring] 0 expiring markets for review
4742
+ [expiring] no expiring markets found this cycle
4743
+ [position-monitor] WARNING: no price data for 553830 NO — first miss recorded, watching (market may be resolved or delisted)
4744
+ [position-monitor] WARNING: no price data for 558934 YES — missing 0.5h (closes after 24h continuous)
4745
+ [position-monitor] WARNING: no price data for 566140 NO — missing 0.5h (closes after 24h continuous)
4746
+ [position-monitor] WARNING: no price data for 540819 NO — missing 0.5h (closes after 24h continuous)
4747
+ [position-monitor] WARNING: no price data for 568629 YES — missing 0.2h (closes after 24h continuous)
4748
+ [position-monitor] checked=22 review_candidates=6 hard_stops=0 (moved>5% or <72h expiry)
4749
+ [polly-gamba] Starting paper trading service
4750
+ [polly-gamba] Claude cwd: /Users/feral/polly-gamba
4751
+ [polly-gamba] Expiring trader cwd: /Users/feral/polly-gamba-expiring
4752
+ [coinbase-ws] Connecting to wss://ws-feed.exchange.coinbase.com
4753
+ [polly-gamba] Listening for BTC/ETH price signals (threshold: 0.5% in 60s)...
4754
+ [scan] fetching high-quality markets (vol24h>$50k, liq>$50k, price 0.10-0.90)
4755
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4756
+ [expiring] fetching expiring markets (closing within 72h, vol24h>$10k, liq>$10k, price 0.05-0.95)
4757
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4758
+ [coinbase-ws] Connected
4759
+ [gamma] Loaded 498 markets (filtered from 500)
4760
+ [expiring] 0 expiring markets for review
4761
+ [expiring] no expiring markets found this cycle
4762
+ [gamma] Loaded 498 markets (filtered from 500)
4763
+ [scan] 17 high-quality markets for autonomous review
4764
+ [position-monitor] checked=22 review_candidates=7 hard_stops=0 (moved>5% or <72h expiry)
4765
+ [claude-trader:anthropic] ready
4766
+ [claude-trader:ollama] ready
4767
+ [claude-trader:expiring] ready
4768
+ [scan] fetching high-quality markets (vol24h>$50k, liq>$50k, price 0.10-0.90)
4769
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4770
+ [expiring] fetching expiring markets (closing within 72h, vol24h>$10k, liq>$10k, price 0.05-0.95)
4771
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4772
+ [scan] failed to fetch markets: fetch failed
4773
+ [expiring] failed to fetch markets: fetch failed
4774
+ [position-monitor] WARNING: no price data for 553830 NO — first miss recorded, watching (market may be resolved or delisted)
4775
+ [position-monitor] WARNING: no price data for 558934 YES — first miss recorded, watching (market may be resolved or delisted)
4776
+ [position-monitor] WARNING: no price data for 566140 NO — first miss recorded, watching (market may be resolved or delisted)
4777
+ [position-monitor] WARNING: no price data for 540819 NO — first miss recorded, watching (market may be resolved or delisted)
4778
+ [position-monitor] WARNING: no price data for 568629 YES — first miss recorded, watching (market may be resolved or delisted)
4779
+ [position-monitor] WARNING: no price data for 558936 YES — first miss recorded, watching (market may be resolved or delisted)
4780
+ [position-monitor] WARNING: no price data for 553866 NO — first miss recorded, watching (market may be resolved or delisted)
4781
+ [position-monitor] WARNING: no price data for 567689 NO — first miss recorded, watching (market may be resolved or delisted)
4782
+ [position-monitor] WARNING: no price data for 566142 NO — first miss recorded, watching (market may be resolved or delisted)
4783
+ [position-monitor] WARNING: no price data for 540844 NO — first miss recorded, watching (market may be resolved or delisted)
4784
+ [position-monitor] WARNING: no price data for 562828 NO — first miss recorded, watching (market may be resolved or delisted)
4785
+ [position-monitor] WARNING: no price data for 566188 NO — first miss recorded, watching (market may be resolved or delisted)
4786
+ [position-monitor] WARNING: no price data for 559651 NO — first miss recorded, watching (market may be resolved or delisted)
4787
+ [position-monitor] WARNING: no price data for 567621 NO — first miss recorded, watching (market may be resolved or delisted)
4788
+ [position-monitor] WARNING: no price data for 561975 NO — first miss recorded, watching (market may be resolved or delisted)
4789
+ [position-monitor] WARNING: no price data for 567561 NO — first miss recorded, watching (market may be resolved or delisted)
4790
+ [position-monitor] WARNING: no price data for 567560 YES — first miss recorded, watching (market may be resolved or delisted)
4791
+ [position-monitor] checked=22 review_candidates=3 hard_stops=0 (moved>5% or <72h expiry)
4792
+ [scan] fetching high-quality markets (vol24h>$50k, liq>$50k, price 0.10-0.90)
4793
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4794
+ [expiring] fetching expiring markets (closing within 72h, vol24h>$10k, liq>$10k, price 0.05-0.95)
4795
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4796
+ [scan] failed to fetch markets: fetch failed
4797
+ [expiring] failed to fetch markets: fetch failed
4798
+ [position-monitor] WARNING: no price data for 553830 NO — missing 0.3h (closes after 24h continuous)
4799
+ [position-monitor] WARNING: no price data for 558934 YES — missing 0.3h (closes after 24h continuous)
4800
+ [position-monitor] WARNING: no price data for 566140 NO — missing 0.3h (closes after 24h continuous)
4801
+ [position-monitor] WARNING: no price data for 540819 NO — missing 0.3h (closes after 24h continuous)
4802
+ [position-monitor] WARNING: no price data for 568629 YES — missing 0.3h (closes after 24h continuous)
4803
+ [position-monitor] WARNING: no price data for 558936 YES — missing 0.3h (closes after 24h continuous)
4804
+ [position-monitor] WARNING: no price data for 553866 NO — missing 0.3h (closes after 24h continuous)
4805
+ [position-monitor] WARNING: no price data for 567689 NO — missing 0.3h (closes after 24h continuous)
4806
+ [position-monitor] WARNING: no price data for 566142 NO — missing 0.3h (closes after 24h continuous)
4807
+ [position-monitor] WARNING: no price data for 540844 NO — missing 0.3h (closes after 24h continuous)
4808
+ [position-monitor] WARNING: no price data for 553862 YES — first miss recorded, watching (market may be resolved or delisted)
4809
+ [position-monitor] WARNING: no price data for 562828 NO — missing 0.3h (closes after 24h continuous)
4810
+ [position-monitor] WARNING: no price data for 566188 NO — missing 0.3h (closes after 24h continuous)
4811
+ [position-monitor] WARNING: no price data for 559651 NO — missing 0.3h (closes after 24h continuous)
4812
+ [position-monitor] WARNING: no price data for 567621 NO — missing 0.3h (closes after 24h continuous)
4813
+ [position-monitor] WARNING: no price data for 560317 NO — first miss recorded, watching (market may be resolved or delisted)
4814
+ [position-monitor] WARNING: no price data for 561230 NO — first miss recorded, watching (market may be resolved or delisted)
4815
+ [position-monitor] WARNING: no price data for 561975 NO — missing 0.3h (closes after 24h continuous)
4816
+ [position-monitor] WARNING: no price data for 567561 NO — missing 0.3h (closes after 24h continuous)
4817
+ [position-monitor] WARNING: no price data for 567560 YES — missing 0.3h (closes after 24h continuous)
4818
+ [position-monitor] WARNING: no price data for 567687 NO — first miss recorded, watching (market may be resolved or delisted)
4819
+ [position-monitor] checked=22 review_candidates=1 hard_stops=0 (moved>5% or <72h expiry)
4820
+ [signal] ETH up 0.51% @ $2,099.48 over 58s
4821
+ [signal] ETH up 0.51% @ $2,099.48
4822
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4823
+ [gamma] Loaded 497 markets (filtered from 500)
4824
+ [match] 20 markets for ETH signal
4825
+ [scan] fetching high-quality markets (vol24h>$50k, liq>$50k, price 0.10-0.90)
4826
+ [scan] 18 high-quality markets for autonomous review
4827
+ [expiring] fetching expiring markets (closing within 72h, vol24h>$10k, liq>$10k, price 0.05-0.95)
4828
+ [expiring] 0 expiring markets for review
4829
+ [expiring] no expiring markets found this cycle
4830
+ [position-monitor] WARNING: no price data for 553830 NO — missing 0.4h (closes after 24h continuous)
4831
+ [position-monitor] WARNING: no price data for 558934 YES — missing 0.4h (closes after 24h continuous)
4832
+ [position-monitor] WARNING: no price data for 566140 NO — missing 0.4h (closes after 24h continuous)
4833
+ [position-monitor] WARNING: no price data for 540819 NO — missing 0.4h (closes after 24h continuous)
4834
+ [position-monitor] WARNING: no price data for 568629 YES — missing 0.4h (closes after 24h continuous)
4835
+ [position-monitor] checked=22 review_candidates=7 hard_stops=0 (moved>5% or <72h expiry)
4836
+ [coinbase-ws] Disconnected — reconnecting in 5s
4837
+ [scan] fetching high-quality markets (vol24h>$50k, liq>$50k, price 0.10-0.90)
4838
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4839
+ [coinbase-ws] Connecting to wss://ws-feed.exchange.coinbase.com
4840
+ [expiring] fetching expiring markets (closing within 72h, vol24h>$10k, liq>$10k, price 0.05-0.95)
4841
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4842
+ [coinbase-ws] Error: write EPIPE
4843
+ [coinbase-ws] Disconnected — reconnecting in 5s
4844
+ [coinbase-ws] Connecting to wss://ws-feed.exchange.coinbase.com
4845
+ [scan] failed to fetch markets: fetch failed
4846
+ [coinbase-ws] Connected
4847
+ [gamma] Loaded 498 markets (filtered from 500)
4848
+ [expiring] 0 expiring markets for review
4849
+ [expiring] no expiring markets found this cycle
4850
+ [position-monitor] WARNING: no price data for 553830 NO — missing 0.7h (closes after 24h continuous)
4851
+ [position-monitor] WARNING: no price data for 558934 YES — missing 0.7h (closes after 24h continuous)
4852
+ [position-monitor] WARNING: no price data for 566140 NO — missing 0.7h (closes after 24h continuous)
4853
+ [position-monitor] WARNING: no price data for 540819 NO — missing 0.7h (closes after 24h continuous)
4854
+ [position-monitor] WARNING: no price data for 568629 YES — missing 0.7h (closes after 24h continuous)
4855
+ [position-monitor] checked=22 review_candidates=7 hard_stops=0 (moved>5% or <72h expiry)
4856
+ [scan] fetching high-quality markets (vol24h>$50k, liq>$50k, price 0.10-0.90)
4857
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4858
+ [scan] failed to fetch markets: fetch failed
4859
+ [position-monitor] checked=21 review_candidates=7 hard_stops=0 (moved>5% or <72h expiry)
4860
+ [signal] BTC up 0.50% @ $69,391.68 over 29s
4861
+ [signal] BTC up 0.50% @ $69,391.68
4862
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4863
+ [gamma] Loaded 497 markets (filtered from 500)
4864
+ [match] 1 markets for BTC signal
4865
+ [signal] ETH up 0.50% @ $2,124.37 over 3s
4866
+ [signal] ETH up 0.50% @ $2,124.37
4867
+ [match] 20 markets for ETH signal
4868
+ [expiring] fetching expiring markets (closing within 72h, vol24h>$10k, liq>$10k, price 0.05-0.95)
4869
+ [expiring] 0 expiring markets for review
4870
+ [expiring] no expiring markets found this cycle
4871
+ [scan] fetching high-quality markets (vol24h>$50k, liq>$50k, price 0.10-0.90)
4872
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4873
+ [scan] failed to fetch markets: fetch failed
4874
+ [position-monitor] WARNING: no price data for 553830 NO — first miss recorded, watching (market may be resolved or delisted)
4875
+ [position-monitor] WARNING: no price data for 558934 YES — first miss recorded, watching (market may be resolved or delisted)
4876
+ [position-monitor] WARNING: no price data for 566140 NO — first miss recorded, watching (market may be resolved or delisted)
4877
+ [position-monitor] WARNING: no price data for 540819 NO — first miss recorded, watching (market may be resolved or delisted)
4878
+ [position-monitor] WARNING: no price data for 568629 YES — first miss recorded, watching (market may be resolved or delisted)
4879
+ [position-monitor] checked=21 review_candidates=6 hard_stops=0 (moved>5% or <72h expiry)
4880
+ [expiring] fetching expiring markets (closing within 72h, vol24h>$10k, liq>$10k, price 0.05-0.95)
4881
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4882
+ [expiring] failed to fetch markets: fetch failed
4883
+ [scan] fetching high-quality markets (vol24h>$50k, liq>$50k, price 0.10-0.90)
4884
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4885
+ [scan] failed to fetch markets: fetch failed
4886
+ [expiring] fetching expiring markets (closing within 72h, vol24h>$10k, liq>$10k, price 0.05-0.95)
4887
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4888
+ [expiring] failed to fetch markets: fetch failed
4889
+ [position-monitor] WARNING: no price data for 553830 NO — missing 0.3h (closes after 24h continuous)
4890
+ [position-monitor] WARNING: no price data for 558934 YES — missing 0.3h (closes after 24h continuous)
4891
+ [position-monitor] WARNING: no price data for 566140 NO — missing 0.3h (closes after 24h continuous)
4892
+ [position-monitor] WARNING: no price data for 540819 NO — missing 0.3h (closes after 24h continuous)
4893
+ [position-monitor] WARNING: no price data for 568629 YES — missing 0.3h (closes after 24h continuous)
4894
+ [position-monitor] WARNING: no price data for 558936 YES — first miss recorded, watching (market may be resolved or delisted)
4895
+ [position-monitor] WARNING: no price data for 553866 NO — first miss recorded, watching (market may be resolved or delisted)
4896
+ [position-monitor] WARNING: no price data for 567689 NO — first miss recorded, watching (market may be resolved or delisted)
4897
+ [position-monitor] WARNING: no price data for 540844 NO — first miss recorded, watching (market may be resolved or delisted)
4898
+ [position-monitor] WARNING: no price data for 553862 YES — first miss recorded, watching (market may be resolved or delisted)
4899
+ [position-monitor] WARNING: no price data for 566188 NO — first miss recorded, watching (market may be resolved or delisted)
4900
+ [position-monitor] WARNING: no price data for 559651 NO — first miss recorded, watching (market may be resolved or delisted)
4901
+ [position-monitor] WARNING: no price data for 567621 NO — first miss recorded, watching (market may be resolved or delisted)
4902
+ [position-monitor] WARNING: no price data for 560317 NO — first miss recorded, watching (market may be resolved or delisted)
4903
+ [position-monitor] checked=21 review_candidates=4 hard_stops=0 (moved>5% or <72h expiry)
4904
+ [scan] fetching high-quality markets (vol24h>$50k, liq>$50k, price 0.10-0.90)
4905
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4906
+ [position-monitor] WARNING: no price data for 566140 NO — missing 0.5h (closes after 24h continuous)
4907
+ [position-monitor] WARNING: no price data for 540819 NO — missing 0.5h (closes after 24h continuous)
4908
+ [gamma] Loaded 498 markets (filtered from 500)
4909
+ [scan] 18 high-quality markets for autonomous review
4910
+ [position-monitor] checked=21 review_candidates=7 hard_stops=0 (moved>5% or <72h expiry)
4911
+ [expiring] fetching expiring markets (closing within 72h, vol24h>$10k, liq>$10k, price 0.05-0.95)
4912
+ [expiring] 0 expiring markets for review
4913
+ [expiring] no expiring markets found this cycle
4914
+ [scan] fetching high-quality markets (vol24h>$50k, liq>$50k, price 0.10-0.90)
4915
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4916
+ [gamma] Loaded 498 markets (filtered from 500)
4917
+ [scan] 18 high-quality markets for autonomous review
4918
+ [position-monitor] WARNING: no price data for 558934 YES — first miss recorded, watching (market may be resolved or delisted)
4919
+ [position-monitor] WARNING: no price data for 568629 YES — first miss recorded, watching (market may be resolved or delisted)
4920
+ [position-monitor] checked=21 review_candidates=6 hard_stops=0 (moved>5% or <72h expiry)
4921
+ [expiring] fetching expiring markets (closing within 72h, vol24h>$10k, liq>$10k, price 0.05-0.95)
4922
+ [expiring] 0 expiring markets for review
4923
+ [expiring] no expiring markets found this cycle
4924
+ [signal] BTC up 0.50% @ $69,709.14 over 59s
4925
+ [signal] BTC up 0.50% @ $69,709.14
4926
+ [match] 1 markets for BTC signal
4927
+ [signal] ETH up 0.50% @ $2,138.63 over 60s
4928
+ [signal] ETH up 0.50% @ $2,138.63
4929
+ [match] 20 markets for ETH signal
4930
+ [scan] fetching high-quality markets (vol24h>$50k, liq>$50k, price 0.10-0.90)
4931
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4932
+ [expiring] fetching expiring markets (closing within 72h, vol24h>$10k, liq>$10k, price 0.05-0.95)
4933
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4934
+ [scan] failed to fetch markets: fetch failed
4935
+ [gamma] Loaded 498 markets (filtered from 500)
4936
+ [expiring] 0 expiring markets for review
4937
+ [expiring] no expiring markets found this cycle
4938
+ [position-monitor] WARNING: no price data for 553830 NO — first miss recorded, watching (market may be resolved or delisted)
4939
+ [position-monitor] WARNING: no price data for 558934 YES — missing 0.4h (closes after 24h continuous)
4940
+ [position-monitor] WARNING: no price data for 566140 NO — first miss recorded, watching (market may be resolved or delisted)
4941
+ [position-monitor] WARNING: no price data for 540819 NO — first miss recorded, watching (market may be resolved or delisted)
4942
+ [position-monitor] WARNING: no price data for 558936 YES — first miss recorded, watching (market may be resolved or delisted)
4943
+ [position-monitor] WARNING: no price data for 567689 NO — first miss recorded, watching (market may be resolved or delisted)
4944
+ [position-monitor] WARNING: no price data for 540844 NO — first miss recorded, watching (market may be resolved or delisted)
4945
+ [position-monitor] WARNING: no price data for 553862 YES — first miss recorded, watching (market may be resolved or delisted)
4946
+ [position-monitor] WARNING: no price data for 562828 NO — first miss recorded, watching (market may be resolved or delisted)
4947
+ [position-monitor] WARNING: no price data for 559651 NO — first miss recorded, watching (market may be resolved or delisted)
4948
+ [position-monitor] WARNING: no price data for 567621 NO — first miss recorded, watching (market may be resolved or delisted)
4949
+ [position-monitor] WARNING: no price data for 560317 NO — first miss recorded, watching (market may be resolved or delisted)
4950
+ [position-monitor] WARNING: no price data for 561975 NO — first miss recorded, watching (market may be resolved or delisted)
4951
+ [position-monitor] WARNING: no price data for 567561 NO — first miss recorded, watching (market may be resolved or delisted)
4952
+ [position-monitor] WARNING: no price data for 567560 YES — first miss recorded, watching (market may be resolved or delisted)
4953
+ [position-monitor] WARNING: no price data for 567687 NO — first miss recorded, watching (market may be resolved or delisted)
4954
+ [position-monitor] checked=21 review_candidates=2 hard_stops=0 (moved>5% or <72h expiry)
4955
+ [signal] ETH down -0.50% @ $2,139.8 over 37s
4956
+ [signal] ETH down 0.50% @ $2,139.8
4957
+ [match] 20 markets for ETH signal
4958
+ [signal] BTC down -0.50% @ $69,838.62 over 60s
4959
+ [signal] BTC down 0.50% @ $69,838.62
4960
+ [match] 1 markets for BTC signal
4961
+ [scan] fetching high-quality markets (vol24h>$50k, liq>$50k, price 0.10-0.90)
4962
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4963
+ [expiring] fetching expiring markets (closing within 72h, vol24h>$10k, liq>$10k, price 0.05-0.95)
4964
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4965
+ [position-monitor] WARNING: no price data for 558934 YES — missing 0.5h (closes after 24h continuous)
4966
+ [position-monitor] WARNING: no price data for 566140 NO — missing 0.2h (closes after 24h continuous)
4967
+ [position-monitor] WARNING: no price data for 540819 NO — missing 0.2h (closes after 24h continuous)
4968
+ [position-monitor] WARNING: no price data for 568629 YES — first miss recorded, watching (market may be resolved or delisted)
4969
+ [position-monitor] WARNING: no price data for 558936 YES — missing 0.2h (closes after 24h continuous)
4970
+ [position-monitor] WARNING: no price data for 567689 NO — missing 0.2h (closes after 24h continuous)
4971
+ [position-monitor] WARNING: no price data for 540844 NO — missing 0.2h (closes after 24h continuous)
4972
+ [position-monitor] WARNING: no price data for 553862 YES — missing 0.2h (closes after 24h continuous)
4973
+ [position-monitor] WARNING: no price data for 560317 NO — missing 0.2h (closes after 24h continuous)
4974
+ [position-monitor] WARNING: no price data for 567687 NO — missing 0.2h (closes after 24h continuous)
4975
+ [position-monitor] checked=21 review_candidates=3 hard_stops=0 (moved>5% or <72h expiry)
4976
+ [gamma] Loaded 498 markets (filtered from 500)
4977
+ [scan] 18 high-quality markets for autonomous review
4978
+ [gamma] Loaded 498 markets (filtered from 500)
4979
+ [expiring] 0 expiring markets for review
4980
+ [expiring] no expiring markets found this cycle
4981
+ [position-monitor] WARNING: no price data for 553830 NO — first miss recorded, watching (market may be resolved or delisted)
4982
+ [position-monitor] WARNING: no price data for 558934 YES — missing 0.8h (closes after 24h continuous)
4983
+ [position-monitor] checked=21 review_candidates=7 hard_stops=0 (moved>5% or <72h expiry)
4984
+ [scan] fetching high-quality markets (vol24h>$50k, liq>$50k, price 0.10-0.90)
4985
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4986
+ [expiring] fetching expiring markets (closing within 72h, vol24h>$10k, liq>$10k, price 0.05-0.95)
4987
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4988
+ [scan] failed to fetch markets: fetch failed
4989
+ [expiring] failed to fetch markets: fetch failed
4990
+ [position-monitor] WARNING: no price data for 558934 YES — missing 1.0h (closes after 24h continuous)
4991
+ [position-monitor] WARNING: no price data for 566140 NO — first miss recorded, watching (market may be resolved or delisted)
4992
+ [position-monitor] WARNING: no price data for 540819 NO — first miss recorded, watching (market may be resolved or delisted)
4993
+ [position-monitor] WARNING: no price data for 568629 YES — first miss recorded, watching (market may be resolved or delisted)
4994
+ [position-monitor] checked=21 review_candidates=6 hard_stops=0 (moved>5% or <72h expiry)
4995
+ [scan] fetching high-quality markets (vol24h>$50k, liq>$50k, price 0.10-0.90)
4996
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
4997
+ [gamma] Loaded 498 markets (filtered from 500)
4998
+ [scan] 18 high-quality markets for autonomous review
4999
+ [expiring] fetching expiring markets (closing within 72h, vol24h>$10k, liq>$10k, price 0.05-0.95)
5000
+ [expiring] 0 expiring markets for review
5001
+ [expiring] no expiring markets found this cycle
5002
+ [signal] BTC up 0.50% @ $70,410.96 over 60s
5003
+ [signal] BTC up 0.50% @ $70,410.96
5004
+ [match] 1 markets for BTC signal
5005
+ [signal] ETH up 0.50% @ $2,162.53 over 59s
5006
+ [signal] ETH up 0.50% @ $2,162.53
5007
+ [match] 20 markets for ETH signal
5008
+ [position-monitor] checked=21 review_candidates=7 hard_stops=0 (moved>5% or <72h expiry)
5009
+ npm warn deprecated prebuild-install@7.1.3: No longer maintained. Please contact the author of the relevant native addon; alternatives are available.
5010
+ [polly-gamba] Starting paper trading service
5011
+ [polly-gamba] Claude cwd: /Users/feral/polly-gamba
5012
+ [polly-gamba] Expiring trader cwd: /Users/feral/polly-gamba-expiring
5013
+ [coinbase-ws] Connecting to wss://ws-feed.exchange.coinbase.com
5014
+ [polly-gamba] Listening for BTC/ETH price signals (threshold: 0.5% in 60s)...
5015
+ [scan] fetching high-quality markets (vol24h>$50k, liq>$50k, price 0.10-0.90)
5016
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
5017
+ [expiring] fetching expiring markets (closing within 72h, vol24h>$10k, liq>$10k, price 0.05-0.95)
5018
+ [gamma] Fetching active markets from https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=500
5019
+ [gamma] Loaded 498 markets (filtered from 500)
5020
+ [scan] 18 high-quality markets for autonomous review
5021
+ [gamma] Loaded 498 markets (filtered from 500)
5022
+ [expiring] 0 expiring markets for review
5023
+ [expiring] no expiring markets found this cycle
5024
+ [coinbase-ws] Connected
5025
+ [position-monitor] checked=21 review_candidates=7 hard_stops=0 (moved>5% or <72h expiry)
5026
+ [claude-trader:anthropic] ready
5027
+ [claude-trader:ollama] ready
5028
+ [claude-trader:expiring] ready
@@ -240,6 +240,7 @@ ${m.description ? `- Description: ${m.description.slice(0, 200)}` : ''}`).join('
240
240
  - Correlation examples: "Will Jesus return before GTA VI", "Will BTC hit $1M before GTA VI", "Will China invade Taiwan before GTA VI" — all three resolve based on GTA VI's release date. They are the SAME theme.
241
241
  - Similarly: "Will Orbán be PM" and "Will Magyar be PM" are both the Hungary 2026 election — treat as same theme (you may hold both as a hedge pair, but do not add a third Hungary position).
242
242
  - IMPORTANT: All 2028 US election markets share one theme — "2028 US election". This includes: Dem primary nominees (Newsom, Harris, etc.), Rep primary nominees (Vance, Rubio, etc.), and the general election winner. Do NOT hold more than 2 positions across this entire cycle.
243
+ - IMPORTANT: All Russia-Ukraine conflict markets share one theme — "Russia-Ukraine conflict". This includes: Putin removal, Zelenskyy removal, ceasefire timing, territorial outcomes, and any other market that resolves based on the Russia-Ukraine war's trajectory. Do NOT hold more than 2 positions across this entire theme.
243
244
  - If you're uncertain whether a market correlates to an existing theme, assume it does and skip.
244
245
 
245
246
  ## CLOSED MARKET DISCIPLINE (absolute rule — never override):
@@ -362,13 +363,13 @@ ${positionLines}
362
363
 
363
364
  CLOSE RULES — apply ALL that match, no thesis override allowed:
364
365
  1. Exit trigger condition has been met (e.g. specific price level hit, event occurred). Apply literally.
365
- 2. Position is down >35% AND the fundamental thesis has materially weakened or been disproven (market structure changed, key assumption invalidated).
366
+ 2. Position is down >35% HARD CLOSE. This is a programmatic rule enforced server-side; by the time you see this position it may already be closed. Do NOT override with thesis defense.
366
367
  3. Your side of the position is priced below 10% — HARD CLOSE. The market has strongly repriced against you. Do NOT override this with "thesis not disproven yet." At <10%, expected value of holding is near zero.
367
368
  4. Position is down >50% — HARD CLOSE regardless of thesis. Cut losses. No exceptions.
368
369
  5. You have 2+ open positions in the SAME market with the SAME outcome — close the NEWER entry (higher ts value) regardless of P&L. Duplicate same-outcome positions double exposure without incremental edge. Keep the original entry.
369
370
  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.
370
371
  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.
371
- 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". IMPORTANT: All positions tied to the 2028 US election cycle share one theme — "2028 US election". This includes: 2028 Dem primary nominees (Newsom, etc.), 2028 Rep primary nominees (Vance, Rubio, etc.), and the 2028 general election winner — regardless of which stage of the race resolves each market. If you have 3+ positions in the same theme: close positions one by one (starting with the one whose current price is closest to 50/50) until you have ≤2 in that theme. If you have 4, you must close 2. If you have 5, close 3. Do NOT stop after closing just one if the theme still has 3+ positions. Apply this BEFORE checking other rules. This check requires the FULL position list — which is why Step 0 mandates calling get_positions first.
372
+ 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". IMPORTANT: All positions tied to the 2028 US election cycle share one theme — "2028 US election". This includes: 2028 Dem primary nominees (Newsom, etc.), 2028 Rep primary nominees (Vance, Rubio, etc.), and the 2028 general election winner — regardless of which stage of the race resolves each market. IMPORTANT: All Russia-Ukraine conflict positions share one theme — "Russia-Ukraine conflict". This includes: Putin removal/survival, Zelenskyy removal/survival, ceasefire timing, territorial outcomes — any market that resolves based on how the Russia-Ukraine war progresses. If you have 3+ positions in the same theme: close positions one by one (starting with the one whose current price is closest to 50/50) until you have ≤2 in that theme. If you have 4, you must close 2. If you have 5, close 3. Do NOT stop after closing just one if the theme still has 3+ positions. Apply this BEFORE checking other rules. This check requires the FULL position list — which is why Step 0 mandates calling get_positions first.
372
373
  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%: CLOSE immediately with reason "thesis_decayed". This is a mechanical rule — a -20% drawdown on a sportsbook arb trade is itself the signal that the cross-market gap has closed or the thesis was wrong. Do NOT attempt to re-estimate current sportsbook consensus or override based on "the sportsbook line is still there." The drawdown is the verdict. No exceptions.
373
374
 
374
375
  HOLD RULES: If NONE of the close rules apply and exit trigger NOT triggered, do nothing (no output needed).
@@ -183,9 +183,9 @@ export class PositionMonitor {
183
183
  const hardStopClosed: string[] = []
184
184
  for (const candidate of reviewCandidates) {
185
185
  const isPriceBelowFloor = candidate.current_price <= 0.10
186
- const isLargeEnoughLoss = candidate.gain_pct <= -0.50
186
+ const isLargeEnoughLoss = candidate.gain_pct <= -0.35
187
187
  if (isPriceBelowFloor || isLargeEnoughLoss) {
188
- await this.executeHardStop(candidate, isPriceBelowFloor ? 'price_below_floor' : 'stop_loss_50pct')
188
+ await this.executeHardStop(candidate, isPriceBelowFloor ? 'price_below_floor' : 'stop_loss_35pct')
189
189
  hardStopClosed.push(candidate.market_id)
190
190
  }
191
191
  }
@@ -366,16 +366,16 @@ async function runHardStopTests(): Promise<void> {
366
366
  assert(isPriceBelowFloor, 'price=0.08 should trigger floor stop')
367
367
  })
368
368
 
369
- await test('F2: loss = -50% triggers stop-loss', async () => {
370
- const gain = -0.50
371
- const isLargeEnoughLoss = gain <= -0.50
372
- assert(isLargeEnoughLoss, 'exactly -50% should trigger stop-loss')
369
+ await test('F2: loss = -35% triggers stop-loss', async () => {
370
+ const gain = -0.35
371
+ const isLargeEnoughLoss = gain <= -0.35
372
+ assert(isLargeEnoughLoss, 'exactly -35% should trigger stop-loss')
373
373
  })
374
374
 
375
- await test('F3: loss = -49.9% does NOT trigger stop-loss', async () => {
376
- const gain = -0.499
377
- const isLargeEnoughLoss = gain <= -0.50
378
- assert(!isLargeEnoughLoss, '-49.9% should NOT trigger stop-loss')
375
+ await test('F3: loss = -34.9% does NOT trigger stop-loss', async () => {
376
+ const gain = -0.349
377
+ const isLargeEnoughLoss = gain <= -0.35
378
+ assert(!isLargeEnoughLoss, '-34.9% should NOT trigger stop-loss')
379
379
  })
380
380
 
381
381
  await test('F4: price = 0.10 triggers floor (boundary — off-by-one vs stated rule)', async () => {
@@ -387,12 +387,12 @@ async function runHardStopTests(): Promise<void> {
387
387
  console.log('\n [NOTE] Boundary: price=0.10 triggers hard stop. Prompt says "<10%" but code uses "<=0.10".')
388
388
  })
389
389
 
390
- await test('F5: price > 0.10 and loss < 50% — no hard stop', async () => {
390
+ await test('F5: price > 0.10 and loss < 35% — no hard stop', async () => {
391
391
  const price = 0.12
392
- const gain = -0.40
392
+ const gain = -0.30
393
393
  const isPriceBelowFloor = price <= 0.10
394
- const isLargeEnoughLoss = gain <= -0.50
395
- assert(!isPriceBelowFloor && !isLargeEnoughLoss, 'price=0.12, -40% should not trigger hard stop')
394
+ const isLargeEnoughLoss = gain <= -0.35
395
+ assert(!isPriceBelowFloor && !isLargeEnoughLoss, 'price=0.12, -30% should not trigger hard stop')
396
396
  })
397
397
  }
398
398