@senpi/runtime 1.0.95-dev.20260409192509 → 1.0.95-dev.20260414143617

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.
Files changed (92) hide show
  1. package/dist/actions/close-position/close-position.action.d.ts.map +1 -1
  2. package/dist/actions/close-position/close-position.action.js +7 -2
  3. package/dist/actions/close-position/close-position.action.js.map +1 -1
  4. package/dist/actions/open-position/open-position.action.d.ts.map +1 -1
  5. package/dist/actions/open-position/open-position.action.js +9 -3
  6. package/dist/actions/open-position/open-position.action.js.map +1 -1
  7. package/dist/cli/guide-commands.d.ts.map +1 -1
  8. package/dist/cli/guide-commands.js +15 -0
  9. package/dist/cli/guide-commands.js.map +1 -1
  10. package/dist/constants/order-types.d.ts +7 -0
  11. package/dist/constants/order-types.d.ts.map +1 -0
  12. package/dist/constants/order-types.js +6 -0
  13. package/dist/constants/order-types.js.map +1 -0
  14. package/dist/dsl/config/exit-block.d.ts +7 -0
  15. package/dist/dsl/config/exit-block.d.ts.map +1 -1
  16. package/dist/dsl/config/parse-plugin-config.d.ts.map +1 -1
  17. package/dist/dsl/config/parse-plugin-config.js +27 -1
  18. package/dist/dsl/config/parse-plugin-config.js.map +1 -1
  19. package/dist/dsl/config/unknown-keys.d.ts.map +1 -1
  20. package/dist/dsl/config/unknown-keys.js +3 -1
  21. package/dist/dsl/config/unknown-keys.js.map +1 -1
  22. package/dist/dsl/monitor/create-monitor.d.ts +4 -0
  23. package/dist/dsl/monitor/create-monitor.d.ts.map +1 -1
  24. package/dist/dsl/monitor/create-monitor.js +3 -1
  25. package/dist/dsl/monitor/create-monitor.js.map +1 -1
  26. package/dist/dsl/monitor/process-one-position.d.ts +4 -0
  27. package/dist/dsl/monitor/process-one-position.d.ts.map +1 -1
  28. package/dist/dsl/monitor/process-one-position.js +8 -2
  29. package/dist/dsl/monitor/process-one-position.js.map +1 -1
  30. package/dist/dsl/plugin/index.d.ts.map +1 -1
  31. package/dist/dsl/plugin/index.js +2 -0
  32. package/dist/dsl/plugin/index.js.map +1 -1
  33. package/dist/risk/guardrail.types.d.ts +86 -0
  34. package/dist/risk/guardrail.types.d.ts.map +1 -0
  35. package/dist/risk/guardrail.types.js +5 -0
  36. package/dist/risk/guardrail.types.js.map +1 -0
  37. package/dist/risk/index.d.ts +4 -4
  38. package/dist/risk/index.d.ts.map +1 -1
  39. package/dist/risk/index.js +3 -6
  40. package/dist/risk/index.js.map +1 -1
  41. package/dist/risk/risk-audit-log.d.ts +36 -0
  42. package/dist/risk/risk-audit-log.d.ts.map +1 -0
  43. package/dist/risk/risk-audit-log.js +101 -0
  44. package/dist/risk/risk-audit-log.js.map +1 -0
  45. package/dist/risk/risk-guard-helper.d.ts +14 -0
  46. package/dist/risk/risk-guard-helper.d.ts.map +1 -0
  47. package/dist/risk/risk-guard-helper.js +20 -0
  48. package/dist/risk/risk-guard-helper.js.map +1 -0
  49. package/dist/runtime/map-strategies.d.ts.map +1 -1
  50. package/dist/runtime/map-strategies.js +28 -0
  51. package/dist/runtime/map-strategies.js.map +1 -1
  52. package/dist/runtime/risk-guard.d.ts +18 -2
  53. package/dist/runtime/risk-guard.d.ts.map +1 -1
  54. package/dist/runtime/risk-guard.js +229 -5
  55. package/dist/runtime/risk-guard.js.map +1 -1
  56. package/dist/runtime/runtime-schema.d.ts +473 -0
  57. package/dist/runtime/runtime-schema.d.ts.map +1 -1
  58. package/dist/runtime/runtime-schema.js +19 -0
  59. package/dist/runtime/runtime-schema.js.map +1 -1
  60. package/dist/runtime/runtime.d.ts.map +1 -1
  61. package/dist/runtime/runtime.js +16 -2
  62. package/dist/runtime/runtime.js.map +1 -1
  63. package/dist/senpi/client.d.ts +40 -0
  64. package/dist/senpi/client.d.ts.map +1 -1
  65. package/dist/senpi/client.js +64 -0
  66. package/dist/senpi/client.js.map +1 -1
  67. package/dist/senpi/types.d.ts +27 -0
  68. package/dist/senpi/types.d.ts.map +1 -1
  69. package/dist/strategy/strategy-state.d.ts +4 -1
  70. package/dist/strategy/strategy-state.d.ts.map +1 -1
  71. package/dist/strategy/strategy-state.js +7 -2
  72. package/dist/strategy/strategy-state.js.map +1 -1
  73. package/dist/types/action.d.ts +6 -1
  74. package/dist/types/action.d.ts.map +1 -1
  75. package/dist/types/dsl/index.d.ts +3 -0
  76. package/dist/types/dsl/index.d.ts.map +1 -1
  77. package/dist/types/strategy.d.ts +8 -2
  78. package/dist/types/strategy.d.ts.map +1 -1
  79. package/dist/utils/resolve-order-type.d.ts +5 -0
  80. package/dist/utils/resolve-order-type.d.ts.map +1 -0
  81. package/dist/utils/resolve-order-type.js +29 -0
  82. package/dist/utils/resolve-order-type.js.map +1 -0
  83. package/examples/strategies/dsl-showcase.yaml +6 -0
  84. package/examples/strategies/dsl.yaml +4 -0
  85. package/examples/strategies/fox-minimal-loosened.yaml +16 -0
  86. package/examples/strategies/fox-minimal.yaml +17 -1
  87. package/examples/strategies/minimal.yaml +4 -0
  88. package/examples/strategies/risk-showcase.yaml +94 -0
  89. package/examples/strategies/viper.yaml +9 -0
  90. package/examples/strategies/wolf.yaml +9 -0
  91. package/examples/yamls/sample-with-dsl-and-emerging-movers.yaml +10 -1
  92. package/package.json +5 -4
@@ -1,6 +1,22 @@
1
1
  /**
2
- * RiskGuard: gate check and record entry (stub - gate always OPEN, record no-op).
2
+ * RiskGuard: real-time stateless gate evaluation via MCP API calls.
3
+ *
4
+ * All gate decisions are made in real-time — no cached state reads.
5
+ * Every checkGate call logs the decision to the audit log (write-only).
6
+ * If any risk API call fails, the gate is CLOSED (fail-closed).
3
7
  */
4
8
  import type { RiskGuard as IRiskGuard } from "../types/action.js";
5
- export declare function createRiskGuard(): IRiskGuard;
9
+ import type { NotificationService } from "../types/notification.js";
10
+ import type { StrategyConfig } from "../types/strategy.js";
11
+ import type { SenpiClient } from "../senpi/client.js";
12
+ import type { RiskAuditLog } from "../risk/risk-audit-log.js";
13
+ export declare function createRiskGuardStub(): IRiskGuard;
14
+ export interface RiskGuardConfig {
15
+ senpi: SenpiClient;
16
+ notifications: NotificationService;
17
+ strategies: Map<string, StrategyConfig>;
18
+ strategyNames?: Record<string, string>;
19
+ auditLog?: RiskAuditLog;
20
+ }
21
+ export declare function createRiskGuard(config: RiskGuardConfig): IRiskGuard;
6
22
  //# sourceMappingURL=risk-guard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"risk-guard.d.ts","sourceRoot":"","sources":["../../src/runtime/risk-guard.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAmB,SAAS,IAAI,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEnF,wBAAgB,eAAe,IAAI,UAAU,CAS5C"}
1
+ {"version":3,"file":"risk-guard.d.ts","sourceRoot":"","sources":["../../src/runtime/risk-guard.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAmB,SAAS,IAAI,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACnF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAI9D,wBAAgB,mBAAmB,IAAI,UAAU,CAYhD;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,WAAW,CAAC;IACnB,aAAa,EAAE,mBAAmB,CAAC;IACnC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACxC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB;AAcD,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,UAAU,CAoOnE"}
@@ -1,13 +1,237 @@
1
1
  /**
2
- * RiskGuard: gate check and record entry (stub - gate always OPEN, record no-op).
2
+ * RiskGuard: real-time stateless gate evaluation via MCP API calls.
3
+ *
4
+ * All gate decisions are made in real-time — no cached state reads.
5
+ * Every checkGate call logs the decision to the audit log (write-only).
6
+ * If any risk API call fails, the gate is CLOSED (fail-closed).
3
7
  */
4
- export function createRiskGuard() {
8
+ import { isRecord } from "../utils/response.js";
9
+ import { createLogger } from "../utils/logger.js";
10
+ const logger = createLogger("[runtime][risk-guard]");
11
+ export function createRiskGuardStub() {
5
12
  return {
6
- checkGate(_address, _guardRails) {
13
+ async checkGate() {
7
14
  return { gate: "OPEN" };
8
15
  },
9
- recordEntry(_address, _guardRails) {
10
- // no-op
16
+ recordEntry() { },
17
+ async getGateForStrategies(addresses) {
18
+ const out = {};
19
+ for (const addr of addresses)
20
+ out[addr] = { gate: "OPEN" };
21
+ return out;
22
+ },
23
+ };
24
+ }
25
+ /**
26
+ * Extract a verdict boolean from an MCP response envelope.
27
+ * Returns the parsed data object if success=true, or null on failure.
28
+ */
29
+ function extractVerdict(raw) {
30
+ if (!isRecord(raw))
31
+ return null;
32
+ const envelope = raw;
33
+ if (envelope.success === false)
34
+ return null;
35
+ const data = isRecord(envelope.data) ? envelope.data : envelope;
36
+ return data;
37
+ }
38
+ export function createRiskGuard(config) {
39
+ const prevGateState = new Map();
40
+ function strategyKey(address) {
41
+ return config.strategyNames?.[address] ?? `${address.slice(0, 6)}...${address.slice(-4)}`;
42
+ }
43
+ async function logAndNotify(address, result, candidateAsset) {
44
+ const sk = strategyKey(address);
45
+ const curr = `${result.gate}:${result.reason ?? ""}`;
46
+ const prev = prevGateState.get(address);
47
+ if (result.gate !== "OPEN") {
48
+ logger.info("RiskGuard checkGate: gate not OPEN", {
49
+ address: sk,
50
+ gate: result.gate,
51
+ reason: result.reason,
52
+ candidateAsset,
53
+ });
54
+ }
55
+ if (prev !== curr) {
56
+ prevGateState.set(address, curr);
57
+ if (result.gate === "CLOSED") {
58
+ config.notifications.notify(`GATE CLOSED [${sk}]: ${result.reason ?? "unknown"}`).catch(() => { });
59
+ }
60
+ else if (result.gate === "COOLDOWN") {
61
+ config.notifications.notify(`GATE COOLDOWN [${sk}]: ${result.reason ?? "unknown"}`).catch(() => { });
62
+ }
63
+ else if (prev && (prev.startsWith("CLOSED") || prev.startsWith("COOLDOWN"))) {
64
+ config.notifications.notify(`GATE OPEN [${sk}]: previous gate cleared`).catch(() => { });
65
+ }
66
+ }
67
+ if (config.auditLog) {
68
+ await config.auditLog.append({
69
+ ts: new Date().toISOString(),
70
+ event: "gate_check",
71
+ address,
72
+ meta: {
73
+ gate: result.gate,
74
+ reason: result.reason ?? null,
75
+ candidateAsset: candidateAsset ?? null,
76
+ },
77
+ }).catch(() => { });
78
+ }
79
+ }
80
+ /**
81
+ * Evaluate all risk gates in real-time via MCP API calls.
82
+ * Gates are evaluated in order; first CLOSED/COOLDOWN short-circuits.
83
+ * If candidateAsset is provided, per-asset cooldown is also checked.
84
+ */
85
+ async function checkGate(address, opts) {
86
+ const guardRails = config.strategies.get(address)?.guardRails;
87
+ if (!guardRails) {
88
+ return { gate: "OPEN" };
89
+ }
90
+ const { senpi } = config;
91
+ const candidateAsset = opts?.candidateAsset;
92
+ // Gate 1: Daily loss halt + Drawdown halt (via risk snapshot)
93
+ const hasLossLimit = (guardRails.dailyLossLimit != null && guardRails.dailyLossLimit > 0)
94
+ || (guardRails.dailyLossLimitPct != null && guardRails.dailyLossLimitPct > 0);
95
+ const hasDrawdown = guardRails.drawdownHaltPct != null && guardRails.drawdownHaltPct > 0;
96
+ if (hasLossLimit || hasDrawdown) {
97
+ try {
98
+ const raw = await senpi.getDailyRiskSnapshot(address, {
99
+ dailyLossLimitUsd: guardRails.dailyLossLimit,
100
+ dailyLossLimitPct: guardRails.dailyLossLimitPct,
101
+ maxDrawdownPct: guardRails.drawdownHaltPct,
102
+ drawdownResetOnDayRollover: guardRails.drawdownResetOnDayRollover,
103
+ });
104
+ const data = extractVerdict(raw);
105
+ if (!data) {
106
+ const result = { gate: "CLOSED", reason: "Risk snapshot unavailable — fail-closed" };
107
+ await logAndNotify(address, result, candidateAsset);
108
+ return result;
109
+ }
110
+ const hints = data.halt_hints;
111
+ if (hints?.daily_loss_breached) {
112
+ const snap = data.risk_snapshot;
113
+ const pnl = snap?.pnl;
114
+ const result = {
115
+ gate: "CLOSED",
116
+ reason: `Daily loss halt: PnL delta $${(pnl?.delta_since_open ?? 0).toFixed(2)} breached limit`,
117
+ };
118
+ await logAndNotify(address, result, candidateAsset);
119
+ return result;
120
+ }
121
+ if (hints?.drawdown_breached) {
122
+ const snap = data.risk_snapshot;
123
+ const dd = snap?.drawdown;
124
+ const result = {
125
+ gate: "CLOSED",
126
+ reason: `Drawdown halt: ${(dd?.from_peak_pct ?? 0).toFixed(1)}% drop from PnL peak exceeded limit`,
127
+ };
128
+ await logAndNotify(address, result, candidateAsset);
129
+ return result;
130
+ }
131
+ }
132
+ catch (err) {
133
+ logger.warn("getDailyRiskSnapshot failed — fail-closed", { address, err });
134
+ const result = { gate: "CLOSED", reason: "Risk snapshot unavailable — fail-closed" };
135
+ await logAndNotify(address, result, candidateAsset);
136
+ return result;
137
+ }
138
+ }
139
+ // Gate 2: Consecutive loss cooldown
140
+ const hasConsecLoss = guardRails.maxConsecutiveLosses > 0 && guardRails.cooldownMinutes > 0;
141
+ if (hasConsecLoss) {
142
+ try {
143
+ const raw = await senpi.checkConsecutiveLossCooldown(address, guardRails.maxConsecutiveLosses, guardRails.cooldownMinutes);
144
+ const data = extractVerdict(raw);
145
+ if (!data) {
146
+ const result = { gate: "CLOSED", reason: "Consecutive loss cooldown check unavailable — fail-closed" };
147
+ await logAndNotify(address, result, candidateAsset);
148
+ return result;
149
+ }
150
+ if (data.in_cooldown) {
151
+ const result = {
152
+ gate: "COOLDOWN",
153
+ reason: `Consecutive losses: ${data.streak_length ?? "?"} losses in a row, cooldown until ${data.cooldown_expires_at ?? "unknown"}`,
154
+ };
155
+ await logAndNotify(address, result, candidateAsset);
156
+ return result;
157
+ }
158
+ }
159
+ catch (err) {
160
+ logger.warn("checkConsecutiveLossCooldown failed — fail-closed", { address, err });
161
+ const result = { gate: "CLOSED", reason: "Consecutive loss cooldown check unavailable — fail-closed" };
162
+ await logAndNotify(address, result, candidateAsset);
163
+ return result;
164
+ }
165
+ }
166
+ // Gate 3: Per-asset cooldown (only when candidateAsset provided)
167
+ const hasAssetCooldown = guardRails.perAssetCooldownMinutes != null && guardRails.perAssetCooldownMinutes >= 5;
168
+ if (hasAssetCooldown && candidateAsset) {
169
+ try {
170
+ const raw = await senpi.checkAssetCooldown(address, candidateAsset, guardRails.perAssetCooldownMinutes);
171
+ const data = extractVerdict(raw);
172
+ if (!data) {
173
+ const result = { gate: "COOLDOWN", reason: `Asset cooldown check unavailable for ${candidateAsset} — fail-closed` };
174
+ await logAndNotify(address, result, candidateAsset);
175
+ return result;
176
+ }
177
+ if (data.in_cooldown) {
178
+ const result = {
179
+ gate: "COOLDOWN",
180
+ reason: `Asset cooldown: ${candidateAsset} closed at ${data.last_closed_at ?? "unknown"}, cooldown until ${data.cooldown_expires_at ?? "unknown"}`,
181
+ };
182
+ await logAndNotify(address, result, candidateAsset);
183
+ return result;
184
+ }
185
+ }
186
+ catch (err) {
187
+ logger.warn("checkAssetCooldown failed — fail-closed", { address, asset: candidateAsset, err });
188
+ const result = { gate: "COOLDOWN", reason: `Asset cooldown check unavailable for ${candidateAsset} — fail-closed` };
189
+ await logAndNotify(address, result, candidateAsset);
190
+ return result;
191
+ }
192
+ }
193
+ // Gate 4: Max entries per day
194
+ const hasMaxEntries = guardRails.maxEntriesPerDay > 0;
195
+ if (hasMaxEntries) {
196
+ try {
197
+ const raw = await senpi.checkMaxEntries(address, guardRails.maxEntriesPerDay, guardRails.bypassMaxEntriesPerDayOnProfit);
198
+ const data = extractVerdict(raw);
199
+ if (!data) {
200
+ const result = { gate: "CLOSED", reason: "Max entries check unavailable — fail-closed" };
201
+ await logAndNotify(address, result, candidateAsset);
202
+ return result;
203
+ }
204
+ if (!data.gate_open) {
205
+ const result = {
206
+ gate: "CLOSED",
207
+ reason: `Max entries: ${data.entries_today ?? "?"}/${data.max_entries_per_day ?? guardRails.maxEntriesPerDay} entries today${data.bypassed ? " (bypass attempted but not applicable)" : ""}`,
208
+ };
209
+ await logAndNotify(address, result, candidateAsset);
210
+ return result;
211
+ }
212
+ }
213
+ catch (err) {
214
+ logger.warn("checkMaxEntries failed — fail-closed", { address, err });
215
+ const result = { gate: "CLOSED", reason: "Max entries check unavailable — fail-closed" };
216
+ await logAndNotify(address, result, candidateAsset);
217
+ return result;
218
+ }
219
+ }
220
+ const result = { gate: "OPEN" };
221
+ await logAndNotify(address, result, candidateAsset);
222
+ return result;
223
+ }
224
+ return {
225
+ async checkGate(address, opts) {
226
+ return checkGate(address, opts);
227
+ },
228
+ recordEntry() { },
229
+ async getGateForStrategies(addresses) {
230
+ const out = {};
231
+ for (const addr of addresses) {
232
+ out[addr] = await checkGate(addr);
233
+ }
234
+ return out;
11
235
  },
12
236
  };
13
237
  }
@@ -1 +1 @@
1
- {"version":3,"file":"risk-guard.js","sourceRoot":"","sources":["../../src/runtime/risk-guard.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,UAAU,eAAe;IAC7B,OAAO;QACL,SAAS,CAAC,QAAgB,EAAE,WAAqC;YAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAC1B,CAAC;QACD,WAAW,CAAC,QAAgB,EAAE,WAAqC;YACjE,QAAQ;QACV,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"risk-guard.js","sourceRoot":"","sources":["../../src/runtime/risk-guard.ts"],"names":[],"mappings":"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"}