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.
- package/README_FOR_SHARING.md +10 -1
- package/SKILL.md +4 -2
- package/cli/lib/mirror_sync_service.cjs +28 -9
- package/cli/pandora.cjs +36 -6
- package/package.json +1 -1
- package/scripts/.env.example +8 -0
package/README_FOR_SHARING.md
CHANGED
|
@@ -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
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
const
|
|
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,
|
|
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 =
|
|
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
|
-
|
|
6616
|
-
|
|
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
package/scripts/.env.example
CHANGED
|
@@ -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=
|