pandora-cli-skills 1.1.4 → 1.1.6

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.
@@ -35,6 +35,13 @@ Prerequisite: Node.js `>=18`.
35
35
  - `ORACLE`
36
36
  - `FACTORY`
37
37
  - `USDC`
38
+ - optional for live mirror hedging:
39
+ - `POLYMARKET_PRIVATE_KEY`
40
+ - `POLYMARKET_FUNDER`
41
+ - `POLYMARKET_API_KEY`
42
+ - `POLYMARKET_API_SECRET`
43
+ - `POLYMARKET_API_PASSPHRASE`
44
+ - `POLYMARKET_HOST`
38
45
  4. Validate and build:
39
46
  - `npm run doctor`
40
47
  - `npm run build`
@@ -108,7 +115,7 @@ Prerequisite: Node.js `>=18`.
108
115
  - `pandora autopilot once --market-address <0x...> --side no --amount-usdc 10 --trigger-yes-below 15 --paper`
109
116
  - `pandora mirror plan --source polymarket --polymarket-market-id <id> --with-rules --include-similarity`
110
117
  - `pandora mirror verify --pandora-market-address <0x...> --polymarket-market-id <id> --include-similarity`
111
- - `pandora mirror sync once --pandora-market-address <0x...> --polymarket-market-id <id> --paper`
118
+ - `pandora mirror sync once --pandora-market-address <0x...> --polymarket-market-id <id> --paper --hedge-ratio 1.0`
112
119
  - `pandora mirror status --strategy-hash <hash>`
113
120
  - `pandora webhook test --webhook-url https://example.com/hook`
114
121
  - `pandora leaderboard --metric volume --limit 20`
@@ -187,6 +194,8 @@ Prerequisite: Node.js `>=18`.
187
194
  - envelope is `ok=true`, `command="mirror.verify"`, with `data.matchConfidence`, `data.ruleHashLeft`, `data.ruleHashRight`, `data.ruleDiffSummary`, `data.similarityChecks[]`, and `data.gateResult`.
188
195
  - `mirror sync`:
189
196
  - envelope is `ok=true`, `command="mirror.sync"`, with `data.strategyHash`, `data.stateFile`, `data.parameters`, `data.snapshots[]`, and `data.actions[]`.
197
+ - hedge controls: `--hedge-trigger-usdc`, `--max-hedge-usdc`, `--hedge-ratio <n>` (default `1`), and `--no-hedge` to disable hedge execution while keeping drift rebalancing active.
198
+ - rebalance sizing is pool-aware: drift notional scales with `reserveYes + reserveNo`, then bounded by `--max-rebalance-usdc`.
190
199
  - `mirror status`:
191
200
  - envelope is `ok=true`, `command="mirror.status"`, with `data.stateFile`, `data.strategyHash`, and persisted `data.state`.
192
201
  - `webhook test`:
package/SKILL.md CHANGED
@@ -100,7 +100,7 @@ pandora --output json arbitrage --venues pandora,polymarket --min-spread-pct 3 -
100
100
  pandora --output json autopilot once --market-address <0x...> --side no --amount-usdc 10 --trigger-yes-below 15 --paper
101
101
  pandora --output json mirror plan --source polymarket --polymarket-market-id <id> --with-rules --include-similarity
102
102
  pandora --output json mirror verify --pandora-market-address <0x...> --polymarket-market-id <id> --include-similarity
103
- pandora --output json mirror sync once --pandora-market-address <0x...> --polymarket-market-id <id> --paper
103
+ pandora --output json mirror sync once --pandora-market-address <0x...> --polymarket-market-id <id> --paper --hedge-ratio 1.0
104
104
  pandora --output json mirror status --strategy-hash <hash>
105
105
  pandora --output json webhook test --webhook-url https://example.com/hook
106
106
  pandora --output json leaderboard --metric profit --limit 20
@@ -164,7 +164,9 @@ pandora --output json suggest --wallet <0x...> --risk medium --budget 50 --inclu
164
164
  - `mirror plan`: Polymarket mirror sizing plan with liquidity recommendation and distribution hint.
165
165
  - `mirror deploy`: dry-run/execute Pandora AMM deployment from mirror plan inputs.
166
166
  - `mirror verify`: explicit question/rules similarity endpoint for AI-subagent validation.
167
- - `mirror sync`: paper-first delta-neutral loop with strict gates, state persistence, and optional live hedging.
167
+ - `mirror sync`: paper-first delta-neutral loop with strict gates, state persistence, and optional live hedging (`--hedge-ratio <n>`, `--no-hedge`).
168
+ - live hedge env: `POLYMARKET_PRIVATE_KEY`, `POLYMARKET_FUNDER`, `POLYMARKET_API_KEY`, `POLYMARKET_API_SECRET`, `POLYMARKET_API_PASSPHRASE`, `POLYMARKET_HOST`.
169
+ - rebalance sizing is pool-aware and bounded by `--max-rebalance-usdc`.
168
170
  - `mirror status`: local mirror state inspection (no network side effects).
169
171
  - `webhook test`: channel validation for generic, Telegram, and Discord payload delivery.
170
172
  - `leaderboard`: ranked user aggregates by profit/volume/win-rate.
@@ -56,6 +56,7 @@ function evaluateSnapshot(verifyPayload, options) {
56
56
 
57
57
  const reserveYes = toNumber(pandora.reserveYes);
58
58
  const reserveNo = toNumber(pandora.reserveNo);
59
+ const reserveTotalUsdc = reserveYes !== null && reserveNo !== null ? round(reserveYes + reserveNo, 6) : null;
59
60
  const deltaLpUsdc = reserveYes !== null && reserveNo !== null ? round(reserveYes - reserveNo, 6) : null;
60
61
  const targetHedgeUsdc = deltaLpUsdc === null ? null : round(-deltaLpUsdc, 6);
61
62
 
@@ -64,6 +65,9 @@ function evaluateSnapshot(verifyPayload, options) {
64
65
  pandoraYesPct: pandoraYes,
65
66
  driftBps,
66
67
  driftTriggered,
68
+ reserveYesUsdc: reserveYes,
69
+ reserveNoUsdc: reserveNo,
70
+ reserveTotalUsdc,
67
71
  deltaLpUsdc,
68
72
  targetHedgeUsdc,
69
73
  };
@@ -152,6 +156,8 @@ async function runMirrorSync(options, deps = {}) {
152
156
  polymarketSlug: options.polymarketSlug,
153
157
  executeLive: options.executeLive,
154
158
  driftTriggerBps: options.driftTriggerBps,
159
+ hedgeEnabled: options.hedgeEnabled,
160
+ hedgeRatio: options.hedgeRatio,
155
161
  hedgeTriggerUsdc: options.hedgeTriggerUsdc,
156
162
  };
157
163
 
@@ -209,15 +215,20 @@ async function runMirrorSync(options, deps = {}) {
209
215
  snapshotMetrics.targetHedgeUsdc === null
210
216
  ? null
211
217
  : round(snapshotMetrics.targetHedgeUsdc - (toNumber(state.currentHedgeUsdc) || 0), 6);
212
- const hedgeTriggered = gapUsdc !== null && Math.abs(gapUsdc) >= options.hedgeTriggerUsdc;
213
-
214
- const plannedHedgeUsdc = hedgeTriggered
215
- ? Math.min(Math.abs(gapUsdc), options.maxHedgeUsdc)
216
- : 0;
217
-
218
- const driftMagnitudePct = snapshotMetrics.driftBps === null ? 0 : snapshotMetrics.driftBps / 100;
218
+ const rawHedgeTriggered = gapUsdc !== null && Math.abs(gapUsdc) >= options.hedgeTriggerUsdc;
219
+ const hedgeTriggered = Boolean(options.hedgeEnabled) && rawHedgeTriggered;
220
+
221
+ const scaledHedgeUsdc = rawHedgeTriggered ? Math.abs(gapUsdc) * options.hedgeRatio : 0;
222
+ const plannedHedgeUsdc = hedgeTriggered ? Math.min(scaledHedgeUsdc, options.maxHedgeUsdc) : 0;
223
+
224
+ const driftFraction = snapshotMetrics.driftBps === null ? 0 : snapshotMetrics.driftBps / 10_000;
225
+ const rebalanceFromPoolUsdc =
226
+ snapshotMetrics.reserveTotalUsdc === null ? null : snapshotMetrics.reserveTotalUsdc * driftFraction;
227
+ const rebalanceFromDriftPointsUsdc = snapshotMetrics.driftBps === null ? 0 : snapshotMetrics.driftBps / 100;
228
+ const rebalanceSizingBasis = rebalanceFromPoolUsdc === null ? 'drift-points-fallback' : 'pool-size-drift';
229
+ const rebalanceCandidateUsdc = rebalanceFromPoolUsdc === null ? rebalanceFromDriftPointsUsdc : rebalanceFromPoolUsdc;
219
230
  const plannedRebalanceUsdc = snapshotMetrics.driftTriggered
220
- ? Math.min(options.maxRebalanceUsdc, Math.max(1, driftMagnitudePct))
231
+ ? Math.min(options.maxRebalanceUsdc, Math.max(1, rebalanceCandidateUsdc))
221
232
  : 0;
222
233
 
223
234
  const plannedSpendUsdc = round(plannedHedgeUsdc + plannedRebalanceUsdc, 6) || 0;
@@ -249,8 +260,14 @@ async function runMirrorSync(options, deps = {}) {
249
260
  metrics: {
250
261
  ...snapshotMetrics,
251
262
  hedgeGapUsdc: gapUsdc,
263
+ rawHedgeTriggered,
252
264
  hedgeTriggered,
265
+ hedgeEnabled: Boolean(options.hedgeEnabled),
266
+ hedgeRatio: options.hedgeRatio,
267
+ hedgeSuppressed: rawHedgeTriggered && !options.hedgeEnabled,
253
268
  plannedHedgeUsdc,
269
+ rebalanceSizingBasis,
270
+ rebalanceCandidateUsdc: round(rebalanceCandidateUsdc, 6),
254
271
  plannedRebalanceUsdc,
255
272
  plannedSpendUsdc,
256
273
  depthWithinSlippageUsd: depth.depthWithinSlippageUsd,
@@ -314,7 +331,7 @@ async function runMirrorSync(options, deps = {}) {
314
331
  }
315
332
 
316
333
  if (hedgeTriggered && plannedHedgeUsdc > 0) {
317
- const hedgeSide = gapUsdc >= 0 ? 'buy' : 'buy';
334
+ const hedgeSide = 'buy';
318
335
  const tokenId = gapUsdc >= 0 ? verifyPayload.sourceMarket.yesTokenId : verifyPayload.sourceMarket.noTokenId;
319
336
 
320
337
  if (options.executeLive) {
@@ -405,6 +422,8 @@ async function runMirrorSync(options, deps = {}) {
405
422
  intervalMs: options.intervalMs,
406
423
  driftTriggerBps: options.driftTriggerBps,
407
424
  hedgeTriggerUsdc: options.hedgeTriggerUsdc,
425
+ hedgeEnabled: options.hedgeEnabled,
426
+ hedgeRatio: options.hedgeRatio,
408
427
  maxRebalanceUsdc: options.maxRebalanceUsdc,
409
428
  maxHedgeUsdc: options.maxHedgeUsdc,
410
429
  maxOpenExposureUsdc: options.maxOpenExposureUsdc,
package/cli/pandora.cjs CHANGED
@@ -245,7 +245,7 @@ Examples:
245
245
  pandora autopilot once --market-address 0xabc... --side no --amount-usdc 10 --trigger-yes-below 15 --paper
246
246
  pandora mirror plan --source polymarket --polymarket-market-id 0xabc... --with-rules --include-similarity
247
247
  pandora mirror verify --pandora-market-address 0xabc... --polymarket-market-id 0xdef... --include-similarity
248
- pandora mirror sync once --pandora-market-address 0xabc... --polymarket-market-id 0xdef... --paper
248
+ pandora mirror sync once --pandora-market-address 0xabc... --polymarket-market-id 0xdef... --paper --hedge-ratio 1.0
249
249
  pandora webhook test --webhook-url https://example.com/hook --webhook-template '{\"text\":\"{{message}}\"}'
250
250
  pandora leaderboard --metric profit --limit 20
251
251
  pandora analyze --market-address 0xabc... --provider mock
@@ -2938,6 +2938,8 @@ function parseMirrorSyncFlags(args) {
2938
2938
  polymarketMarketId: null,
2939
2939
  polymarketSlug: null,
2940
2940
  executeLive: false,
2941
+ hedgeEnabled: true,
2942
+ hedgeRatio: 1,
2941
2943
  intervalMs: 5_000,
2942
2944
  driftTriggerBps: 150,
2943
2945
  hedgeTriggerUsdc: 10,
@@ -2995,6 +2997,10 @@ function parseMirrorSyncFlags(args) {
2995
2997
  options.executeLive = true;
2996
2998
  continue;
2997
2999
  }
3000
+ if (token === '--no-hedge') {
3001
+ options.hedgeEnabled = false;
3002
+ continue;
3003
+ }
2998
3004
  if (token === '--interval-ms') {
2999
3005
  options.intervalMs = parsePositiveInteger(requireFlagValue(rest, i, '--interval-ms'), '--interval-ms');
3000
3006
  if (options.intervalMs < 1_000) {
@@ -3013,6 +3019,14 @@ function parseMirrorSyncFlags(args) {
3013
3019
  i += 1;
3014
3020
  continue;
3015
3021
  }
3022
+ if (token === '--hedge-ratio') {
3023
+ options.hedgeRatio = parsePositiveNumber(requireFlagValue(rest, i, '--hedge-ratio'), '--hedge-ratio');
3024
+ if (options.hedgeRatio > 2) {
3025
+ throw new CliError('INVALID_FLAG_VALUE', '--hedge-ratio must be <= 2.');
3026
+ }
3027
+ i += 1;
3028
+ continue;
3029
+ }
3016
3030
  if (token === '--max-rebalance-usdc') {
3017
3031
  options.maxRebalanceUsdc = parsePositiveNumber(requireFlagValue(rest, i, '--max-rebalance-usdc'), '--max-rebalance-usdc');
3018
3032
  i += 1;
@@ -3140,6 +3154,8 @@ function parseMirrorSyncFlags(args) {
3140
3154
  polymarketSlug: options.polymarketSlug,
3141
3155
  executeLive: options.executeLive,
3142
3156
  driftTriggerBps: options.driftTriggerBps,
3157
+ hedgeEnabled: options.hedgeEnabled,
3158
+ hedgeRatio: options.hedgeRatio,
3143
3159
  hedgeTriggerUsdc: options.hedgeTriggerUsdc,
3144
3160
  });
3145
3161
  }
@@ -4175,6 +4191,8 @@ function renderAutopilotTable(data) {
4175
4191
  [
4176
4192
  ['mode', data.mode],
4177
4193
  ['executeLive', data.executeLive ? 'yes' : 'no'],
4194
+ ['hedgeEnabled', data.parameters && data.parameters.hedgeEnabled === false ? 'no' : 'yes'],
4195
+ ['hedgeRatio', data.parameters && data.parameters.hedgeRatio !== undefined ? data.parameters.hedgeRatio : ''],
4178
4196
  ['strategyHash', data.strategyHash],
4179
4197
  ['iterationsCompleted', data.iterationsCompleted],
4180
4198
  ['actionCount', data.actionCount],
@@ -6471,7 +6489,7 @@ async function runMirrorCommand(args, context) {
6471
6489
  ' verify --pandora-market-address <address> --polymarket-market-id <id>|--polymarket-slug <slug> [--include-similarity] [--with-rules]',
6472
6490
  );
6473
6491
  console.log(
6474
- ' sync run|once --pandora-market-address <address> --polymarket-market-id <id>|--polymarket-slug <slug> [--paper|--execute-live] [--interval-ms <ms>] [--drift-trigger-bps <n>] [--hedge-trigger-usdc <n>] [--max-rebalance-usdc <n>] [--max-hedge-usdc <n>] [--max-open-exposure-usdc <n>] [--max-trades-per-day <n>] [--cooldown-ms <ms>] [--state-file <path>] [--kill-switch-file <path>]',
6492
+ ' sync run|once --pandora-market-address <address> --polymarket-market-id <id>|--polymarket-slug <slug> [--paper|--execute-live] [--interval-ms <ms>] [--drift-trigger-bps <n>] [--hedge-trigger-usdc <n>] [--hedge-ratio <n>] [--no-hedge] [--max-rebalance-usdc <n>] [--max-hedge-usdc <n>] [--max-open-exposure-usdc <n>] [--max-trades-per-day <n>] [--cooldown-ms <ms>] [--state-file <path>] [--kill-switch-file <path>]',
6475
6493
  );
6476
6494
  console.log(' status --state-file <path>|--strategy-hash <hash>');
6477
6495
  }
@@ -6612,13 +6630,25 @@ async function runMirrorCommand(args, context) {
6612
6630
  emitSuccess(
6613
6631
  context.outputMode,
6614
6632
  'mirror.sync.help',
6615
- commandHelpPayload(
6616
- 'pandora [--output table|json] mirror sync run|once --pandora-market-address <address> --polymarket-market-id <id>|--polymarket-slug <slug> [--paper|--execute-live] [--interval-ms <ms>] [--drift-trigger-bps <n>] [--hedge-trigger-usdc <n>] [--max-rebalance-usdc <n>] [--max-hedge-usdc <n>] [--max-open-exposure-usdc <n>] [--max-trades-per-day <n>] [--cooldown-ms <ms>] [--state-file <path>] [--kill-switch-file <path>]',
6617
- ),
6633
+ {
6634
+ usage:
6635
+ 'pandora [--output table|json] mirror sync run|once --pandora-market-address <address> --polymarket-market-id <id>|--polymarket-slug <slug> [--paper|--execute-live] [--interval-ms <ms>] [--drift-trigger-bps <n>] [--hedge-trigger-usdc <n>] [--hedge-ratio <n>] [--no-hedge] [--max-rebalance-usdc <n>] [--max-hedge-usdc <n>] [--max-open-exposure-usdc <n>] [--max-trades-per-day <n>] [--cooldown-ms <ms>] [--state-file <path>] [--kill-switch-file <path>]',
6636
+ liveHedgeEnv: [
6637
+ 'POLYMARKET_PRIVATE_KEY',
6638
+ 'POLYMARKET_FUNDER',
6639
+ 'POLYMARKET_API_KEY',
6640
+ 'POLYMARKET_API_SECRET',
6641
+ 'POLYMARKET_API_PASSPHRASE',
6642
+ 'POLYMARKET_HOST',
6643
+ ],
6644
+ },
6618
6645
  );
6619
6646
  } else {
6620
6647
  console.log(
6621
- 'Usage: pandora [--output table|json] mirror sync run|once --pandora-market-address <address> --polymarket-market-id <id>|--polymarket-slug <slug> [--paper|--execute-live] [--interval-ms <ms>] [--drift-trigger-bps <n>] [--hedge-trigger-usdc <n>] [--max-rebalance-usdc <n>] [--max-hedge-usdc <n>] [--max-open-exposure-usdc <n>] [--max-trades-per-day <n>] [--cooldown-ms <ms>] [--state-file <path>] [--kill-switch-file <path>]',
6648
+ 'Usage: pandora [--output table|json] mirror sync run|once --pandora-market-address <address> --polymarket-market-id <id>|--polymarket-slug <slug> [--paper|--execute-live] [--interval-ms <ms>] [--drift-trigger-bps <n>] [--hedge-trigger-usdc <n>] [--hedge-ratio <n>] [--no-hedge] [--max-rebalance-usdc <n>] [--max-hedge-usdc <n>] [--max-open-exposure-usdc <n>] [--max-trades-per-day <n>] [--cooldown-ms <ms>] [--state-file <path>] [--kill-switch-file <path>]',
6649
+ );
6650
+ console.log(
6651
+ 'Live hedge env: POLYMARKET_PRIVATE_KEY, POLYMARKET_FUNDER, POLYMARKET_API_KEY, POLYMARKET_API_SECRET, POLYMARKET_API_PASSPHRASE, POLYMARKET_HOST.',
6622
6652
  );
6623
6653
  }
6624
6654
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pandora-cli-skills",
3
- "version": "1.1.4",
3
+ "version": "1.1.6",
4
4
  "description": "Pandora CLI & Skills",
5
5
  "main": "cli/pandora.cjs",
6
6
  "bin": {
@@ -5,3 +5,11 @@ PRIVATE_KEY=0x...
5
5
  ORACLE=0x259308E7d8557e4Ba192De1aB8Cf7e0E21896442
6
6
  FACTORY=0xaB120F1FD31FB1EC39893B75d80a3822b1Cd8d0c
7
7
  USDC=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
8
+
9
+ # Optional: Polymarket live hedging credentials for `pandora mirror sync --execute-live`
10
+ POLYMARKET_HOST=https://clob.polymarket.com
11
+ POLYMARKET_PRIVATE_KEY=0x...
12
+ POLYMARKET_FUNDER=
13
+ POLYMARKET_API_KEY=
14
+ POLYMARKET_API_SECRET=
15
+ POLYMARKET_API_PASSPHRASE=