@tradejs/types 1.0.9 → 1.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -42,15 +42,109 @@ interface MonthlyEquityStats {
42
42
  maxMonthlyGain: number;
43
43
  maxMonthlyDrop: number;
44
44
  }
45
- type ThresholdLevel = 'error' | 'warning' | 'success';
45
+ type ThresholdLevel = 'error' | 'warning' | 'success' | 'neutral';
46
46
  interface MetricThreshold {
47
47
  thresholds: [number, number];
48
48
  direction: 'higher' | 'lower';
49
49
  isPercent?: boolean;
50
50
  isAmount?: boolean;
51
+ neutralValue?: number;
51
52
  precision: number;
52
53
  }
53
54
 
55
+ type MarketUniverse = 'crypto' | 'tradfi';
56
+ type AssetClass = 'crypto' | 'equity' | 'commodity' | 'forex';
57
+ type InstrumentKind = 'perpetual' | 'spot';
58
+ type InstrumentStatus = 'trading' | 'inactive' | 'unknown';
59
+ interface InstrumentDescriptor {
60
+ provider: string;
61
+ symbol: string;
62
+ kind: InstrumentKind;
63
+ assetClass: AssetClass;
64
+ universe: MarketUniverse;
65
+ status: InstrumentStatus;
66
+ baseAsset?: string;
67
+ quoteAsset?: string;
68
+ settleAsset?: string;
69
+ displayName?: string;
70
+ venueMetadata?: Record<string, unknown>;
71
+ }
72
+ interface ConnectorCapabilities {
73
+ supportedUniverses: readonly MarketUniverse[];
74
+ defaultUniverse: MarketUniverse;
75
+ }
76
+ interface InstrumentQuery {
77
+ universe?: MarketUniverse;
78
+ assetClasses?: readonly AssetClass[];
79
+ symbols?: readonly string[];
80
+ }
81
+ interface TickerQuery extends InstrumentQuery {
82
+ }
83
+ interface FundingRatePoint {
84
+ symbol: string;
85
+ timestamp: number;
86
+ rate: number;
87
+ }
88
+ interface FundingRateHistoryRequest {
89
+ symbol: string;
90
+ startTime?: number;
91
+ endTime: number;
92
+ limit?: number;
93
+ }
94
+ interface TradingFeeRate {
95
+ symbol: string;
96
+ makerRate: number;
97
+ takerRate: number;
98
+ source: 'exchange-account' | 'connector-default' | 'fallback';
99
+ capturedAt: number;
100
+ }
101
+ interface TradingAccountRef {
102
+ id: string;
103
+ label: string;
104
+ provider: string;
105
+ enabled: boolean;
106
+ isDefault?: boolean;
107
+ universes: MarketUniverse[];
108
+ environment: 'mainnet' | 'testnet';
109
+ apiKey?: string;
110
+ apiSecret?: string;
111
+ uid?: string;
112
+ readOnly?: boolean;
113
+ lastCheckedAt?: number;
114
+ lastError?: string;
115
+ }
116
+ interface RuntimeDeploymentStrategy {
117
+ strategyName: string;
118
+ policyProfileId: string;
119
+ enabled?: boolean;
120
+ config?: Record<string, unknown>;
121
+ }
122
+ interface RuntimeDeployment {
123
+ id: string;
124
+ label: string;
125
+ connectorName: string;
126
+ provider: string;
127
+ accountId: string;
128
+ universe: MarketUniverse;
129
+ interval: string;
130
+ enabled: boolean;
131
+ strategies: RuntimeDeploymentStrategy[];
132
+ assetClasses?: AssetClass[];
133
+ tickers?: string[];
134
+ }
135
+ interface RuntimeDeploymentHeartbeat {
136
+ deploymentId: string;
137
+ status: 'running' | 'stopped' | 'error';
138
+ pid: number;
139
+ startedAt: number;
140
+ lastCycleAt: number;
141
+ lastError?: string;
142
+ }
143
+ type MarketDataCapability = 'target.mtf' | 'target.funding' | 'target.openInterest' | 'crypto.btcReference' | 'crypto.ethReference' | 'crypto.derivatives' | 'crypto.marketBreadth' | 'crypto.crossVenueSpread' | 'crypto.coinMarketCap';
144
+ declare const DEFAULT_MARKET_UNIVERSE: MarketUniverse;
145
+ declare const isMarketUniverse: (value: unknown) => value is MarketUniverse;
146
+ declare const resolveConnectorUniverse: (capabilities: ConnectorCapabilities, requested?: unknown) => MarketUniverse;
147
+
54
148
  type Interval = KlineIntervalV3;
55
149
  type Provider = 'bybit' | 'binance' | 'coinbase';
56
150
  interface Candle {
@@ -61,12 +155,26 @@ interface Candle {
61
155
  volume: number;
62
156
  timestamp: number;
63
157
  turnover: number;
158
+ trades?: number | null;
159
+ takerBuyBaseVolume?: number | null;
160
+ takerBuyQuoteVolume?: number | null;
161
+ takerSellBaseVolume?: number | null;
162
+ takerSellQuoteVolume?: number | null;
64
163
  }
65
164
  interface KlineChartItem extends Candle {
66
165
  dt: string;
67
166
  [key: string]: unknown;
68
167
  }
69
168
  type KlineChartData = Array<KlineChartItem>;
169
+ interface MarketKlineEvent {
170
+ provider: Provider;
171
+ universe: MarketUniverse;
172
+ symbol: string;
173
+ interval: Interval;
174
+ candle: KlineChartItem;
175
+ confirm: boolean;
176
+ receivedAt: number;
177
+ }
70
178
  interface KlineRequest {
71
179
  symbol: string;
72
180
  interval: Interval;
@@ -89,6 +197,7 @@ type DerivativesRow = {
89
197
  source?: string | null;
90
198
  };
91
199
  type DerivativesPressure = 'neutral' | 'crowded_long' | 'crowded_short' | 'long_flush' | 'short_flush';
200
+ type DerivativesPriceOiDivergenceType = 'price_up_oi_up' | 'price_up_oi_down' | 'price_down_oi_up' | 'price_down_oi_down' | 'flat_or_mixed' | 'unknown';
92
201
  type DerivativesContextRiskFlag = 'missing_derivatives' | 'stale_derivatives' | 'crowded_long' | 'crowded_short' | 'oi_falling' | 'oi_not_confirming' | 'long_liquidation_spike' | 'short_liquidation_spike';
93
202
  interface DerivativesIntervalContext {
94
203
  interval: DerivativesInterval;
@@ -116,13 +225,41 @@ interface DerivativesSymbolContext {
116
225
  pressure: DerivativesPressure;
117
226
  directionAligned: boolean | null;
118
227
  riskFlags: DerivativesContextRiskFlag[];
228
+ fundingChange1h?: number | null;
229
+ oiAcceleration?: number | null;
230
+ priceOiDivergenceType?: DerivativesPriceOiDivergenceType;
231
+ crowdingPersistenceBars?: number | null;
119
232
  };
120
233
  }
234
+ interface DerivativesTargetDerivedContext {
235
+ available: boolean;
236
+ stale: boolean | null;
237
+ sourceSymbol: string;
238
+ referenceSymbol: string | null;
239
+ directionAligned: boolean | null;
240
+ referenceDirectionAligned: boolean | null;
241
+ pressure: DerivativesPressure | null;
242
+ referencePressure: DerivativesPressure | null;
243
+ riskFlags: DerivativesContextRiskFlag[];
244
+ oiChangePct1h: number | null;
245
+ oiAcceleration: number | null;
246
+ fundingRate: number | null;
247
+ fundingZScore: number | null;
248
+ fundingChange1h: number | null;
249
+ liqSpikeRatio: number | null;
250
+ liqImbalance: number | null;
251
+ targetVsPrimaryOiChangePct1hDelta: number | null;
252
+ targetVsPrimaryFundingZScoreDelta: number | null;
253
+ targetReferenceConflict: boolean | null;
254
+ }
121
255
  interface DerivativesContext extends DerivativesSymbolContext {
122
256
  targetSymbol?: string;
123
257
  primaryReferenceSymbol?: string;
258
+ secondaryReferenceSymbol?: string;
124
259
  referenceSymbols?: string[];
125
260
  referenceContexts?: Record<string, DerivativesSymbolContext>;
261
+ targetContext?: DerivativesSymbolContext;
262
+ targetDerived?: DerivativesTargetDerivedContext;
126
263
  }
127
264
  type SpreadRow = {
128
265
  symbol: string;
@@ -133,6 +270,128 @@ type SpreadRow = {
133
270
  spread?: number | null;
134
271
  source?: string | null;
135
272
  };
273
+ type MarketFeatureInterval = '1m' | '5m' | '15m' | '1h';
274
+ type MarketGlobalContextSource = 'coinmarketcap_global';
275
+ type MarketGlobalContextRow = {
276
+ source: MarketGlobalContextSource;
277
+ ts: Date;
278
+ updatedAt?: Date | null;
279
+ activeCryptocurrencies?: number | null;
280
+ activeExchanges?: number | null;
281
+ activeMarketPairs?: number | null;
282
+ markets?: number | null;
283
+ totalMarketCapUsd?: number | null;
284
+ totalVolumeUsd?: number | null;
285
+ totalVolumeReportedUsd?: number | null;
286
+ btcDominancePct?: number | null;
287
+ ethDominancePct?: number | null;
288
+ altMarketCapUsd?: number | null;
289
+ altVolumeUsd?: number | null;
290
+ altVolumeReportedUsd?: number | null;
291
+ btcToAltMarketCapRatio?: number | null;
292
+ marketCapChangePct24hUsd?: number | null;
293
+ };
294
+ type MarketReferenceAssetContextRow = {
295
+ source: 'coinmarketcap_reference_asset';
296
+ symbol: 'BTCUSDT' | 'ETHUSDT' | string;
297
+ cmcId: number;
298
+ interval: '1d';
299
+ ts: Date;
300
+ openUsd?: number | null;
301
+ highUsd?: number | null;
302
+ lowUsd?: number | null;
303
+ closeUsd?: number | null;
304
+ volumeUsd?: number | null;
305
+ marketCapUsd?: number | null;
306
+ };
307
+ type CmcExchangeLiquidityRegime = 'expanding' | 'contracting' | 'binance_led' | 'concentrated' | 'balanced' | 'thin' | 'unknown';
308
+ type MarketCmcExchangeLiquidityContextRow = {
309
+ source: 'coinmarketcap_exchange_liquidity';
310
+ interval: '1d' | '1h';
311
+ ts: Date;
312
+ exchangesCount: number;
313
+ totalVolumeUsd?: number | null;
314
+ binanceVolumeUsd?: number | null;
315
+ binanceVolumeShare?: number | null;
316
+ topExchangeVolumeShare?: number | null;
317
+ liquidityRegime?: CmcExchangeLiquidityRegime | null;
318
+ };
319
+ type CmcFearGreedClassification = 'Extreme Fear' | 'Fear' | 'Neutral' | 'Greed' | 'Extreme Greed' | 'Unknown';
320
+ type CmcFearGreedRegime = 'capitulation' | 'risk_off' | 'neutral' | 'risk_on' | 'euphoric' | 'unknown';
321
+ type MarketCmcFearGreedContextRow = {
322
+ source: 'coinmarketcap_fear_greed';
323
+ interval: '1d';
324
+ ts: Date;
325
+ value: number;
326
+ classification: CmcFearGreedClassification;
327
+ sentimentRegime: CmcFearGreedRegime;
328
+ };
329
+ type MarketCmcIndexSlug = 'cmc100' | 'cmc20';
330
+ type MarketCmcIndexConstituent = {
331
+ id?: number | null;
332
+ name?: string | null;
333
+ symbol?: string | null;
334
+ url?: string | null;
335
+ weightPct?: number | null;
336
+ priceUsd?: number | null;
337
+ units?: number | null;
338
+ };
339
+ type MarketCmcIndexContextRow = {
340
+ source: 'coinmarketcap_index';
341
+ indexSlug: MarketCmcIndexSlug;
342
+ interval: '1d';
343
+ ts: Date;
344
+ value: number;
345
+ constituentsCount?: number | null;
346
+ topConstituentSymbol?: string | null;
347
+ topConstituentWeightPct?: number | null;
348
+ constituents?: MarketCmcIndexConstituent[] | null;
349
+ };
350
+ type MarketBreadthRow = {
351
+ universe: string;
352
+ interval: MarketFeatureInterval;
353
+ ts: Date;
354
+ symbolsCount: number;
355
+ advancers: number;
356
+ decliners: number;
357
+ unchanged: number;
358
+ advanceDeclineRatio?: number | null;
359
+ pctAboveMa20?: number | null;
360
+ pctAboveMa50?: number | null;
361
+ equalWeightedReturn?: number | null;
362
+ volumeWeightedReturn?: number | null;
363
+ dispersion?: number | null;
364
+ btcReturn1h?: number | null;
365
+ btcReturn4h?: number | null;
366
+ btcReturn24h?: number | null;
367
+ altBasketReturn1h?: number | null;
368
+ altBasketReturn4h?: number | null;
369
+ altBasketReturn24h?: number | null;
370
+ btcVsAltReturn1h?: number | null;
371
+ btcVsAltReturn4h?: number | null;
372
+ btcVsAltReturn24h?: number | null;
373
+ btcTurnoverShare1h?: number | null;
374
+ btcTurnoverShare24h?: number | null;
375
+ btcTurnoverShareChange24h?: number | null;
376
+ altVolToBtcVol24h?: number | null;
377
+ altDispersion24h?: number | null;
378
+ btcAltRegime?: 'btc_lead' | 'alt_lead' | 'risk_off' | 'risk_on' | 'mixed' | 'neutral' | 'unknown' | null;
379
+ source?: string | null;
380
+ };
381
+ type MarketTradeFlowRow = {
382
+ symbol: string;
383
+ interval: MarketFeatureInterval;
384
+ ts: Date;
385
+ trades: number;
386
+ buyBaseVolume?: number | null;
387
+ sellBaseVolume?: number | null;
388
+ buyQuoteVolume?: number | null;
389
+ sellQuoteVolume?: number | null;
390
+ netBaseDelta?: number | null;
391
+ netQuoteDelta?: number | null;
392
+ buyPressurePct?: number | null;
393
+ source?: string | null;
394
+ };
136
395
  interface Tp {
137
396
  price: number;
138
397
  rate: number;
@@ -148,6 +407,7 @@ type Order = {
148
407
  price: number;
149
408
  timestamp: number;
150
409
  direction: Direction;
410
+ leverage?: number;
151
411
  orderId?: string;
152
412
  signal?: Signal;
153
413
  };
@@ -160,11 +420,17 @@ type Position = {
160
420
  interface PositionPnlSnapshot extends Position {
161
421
  currentPrice: number;
162
422
  unrealizedPnl: number;
423
+ takeProfitPrice?: number | null;
424
+ stopLossPrice?: number | null;
425
+ fundingFee?: number | null;
163
426
  }
164
427
  type OrderType = 'OPEN_LONG' | 'OPEN_SHORT' | 'CLOSE_LONG' | 'CLOSE_SHORT' | 'TAKE_PROFIT_LONG' | 'TAKE_PROFIT_SHORT' | 'STOP_LOSS_LONG' | 'STOP_LOSS_SHORT';
165
428
  type ConnectorCreator = (config: ConnectorConfig) => Promise<Connector>;
166
429
  interface ConnectorConfig {
167
430
  userName: string;
431
+ accountId?: string;
432
+ deploymentId?: string;
433
+ universe?: MarketUniverse;
168
434
  }
169
435
  interface ConnectorRegistryEntry {
170
436
  name: string;
@@ -184,7 +450,32 @@ interface ClosedPnlRecord {
184
450
  exitPrice: number | null;
185
451
  closedPnl: number;
186
452
  closedAt: number;
453
+ direction?: Direction;
454
+ entryTimestamp?: number;
187
455
  orderId?: string;
456
+ orderLinkId?: string;
457
+ openFee?: number | null;
458
+ closeFee?: number | null;
459
+ fundingFee?: number | null;
460
+ totalFee?: number | null;
461
+ }
462
+ interface ExchangeEntryRecord {
463
+ symbol: string;
464
+ qty: number;
465
+ entryPrice: number | null;
466
+ entryTimestamp: number;
467
+ direction: Direction;
468
+ orderId?: string;
469
+ orderLinkId?: string;
470
+ takeProfitPrice?: number | null;
471
+ stopLossPrice?: number | null;
472
+ exitPrice?: number | null;
473
+ exitTimestamp?: number | null;
474
+ closedPnl?: number | null;
475
+ openFee?: number | null;
476
+ closeFee?: number | null;
477
+ fundingFee?: number | null;
478
+ totalFee?: number | null;
188
479
  }
189
480
  interface GetClosedPnlParams {
190
481
  startTime: number;
@@ -193,6 +484,7 @@ interface GetClosedPnlParams {
193
484
  limit?: number;
194
485
  }
195
486
  type GetClosedPnl = (params: GetClosedPnlParams) => Promise<ClosedPnlRecord[]>;
487
+ type GetEntryExecutions = (params: GetClosedPnlParams) => Promise<ExchangeEntryRecord[]>;
196
488
  type PlaceOrder = (order: Order) => Promise<boolean>;
197
489
  type ClosePosition = (order: Omit<Order, 'qty'>) => Promise<boolean>;
198
490
  type SetTakeProfits = (params: {
@@ -207,8 +499,19 @@ type SetStopLoss = (params: {
207
499
  stopLossPrice: Sl;
208
500
  }) => Promise<boolean>;
209
501
  type Kline = (options: KlineRequest) => Promise<KlineChartData>;
210
- type GetTickers = () => Promise<Ticker[]>;
502
+ type GetTickers = (query?: TickerQuery) => Promise<Ticker[]>;
503
+ type ListInstruments = (query?: InstrumentQuery) => Promise<InstrumentDescriptor[]>;
504
+ type GetFundingRateHistory = (request: FundingRateHistoryRequest) => Promise<FundingRatePoint[]>;
505
+ type GetTradingFeeRate = (symbol: string) => Promise<TradingFeeRate | null>;
506
+ type GetTopOfBookTicker = (symbol: string) => Promise<TopOfBookTicker | null>;
507
+ type GetAggTrades = (request: AggTradesRequest) => Promise<AggTrade[]>;
508
+ type GetOrderBookDepth = (request: OrderBookDepthRequest) => Promise<OrderBookDepth | null>;
211
509
  interface Connector {
510
+ capabilities: ConnectorCapabilities;
511
+ universe: MarketUniverse;
512
+ accountId?: string;
513
+ deploymentId?: string;
514
+ listInstruments: ListInstruments;
212
515
  kline: Kline;
213
516
  getState: () => Promise<object>;
214
517
  setState: (state: object) => Promise<void>;
@@ -216,11 +519,17 @@ interface Connector {
216
519
  getPositions: GetPositions;
217
520
  getOpenPositionPnl?: GetOpenPositionPnl;
218
521
  getClosedPnl?: GetClosedPnl;
522
+ getEntryExecutions?: GetEntryExecutions;
219
523
  placeOrder: PlaceOrder;
220
524
  setTakeProfits: SetTakeProfits;
221
525
  setStopLoss: SetStopLoss;
222
526
  closePosition: ClosePosition;
223
527
  getTickers: GetTickers;
528
+ getFundingRateHistory?: GetFundingRateHistory;
529
+ getTradingFeeRate?: GetTradingFeeRate;
530
+ getTopOfBookTicker?: GetTopOfBookTicker;
531
+ getAggTrades?: GetAggTrades;
532
+ getOrderBookDepth?: GetOrderBookDepth;
224
533
  }
225
534
  interface Indicator {
226
535
  id: string;
@@ -231,6 +540,7 @@ interface Indicator {
231
540
  type Indicators = Indicator[];
232
541
  interface Filters {
233
542
  provider?: Provider;
543
+ universe?: MarketUniverse;
234
544
  symbol: string;
235
545
  interval: Interval;
236
546
  start: number;
@@ -264,6 +574,40 @@ interface Ticker {
264
574
  preOpenPrice: string;
265
575
  preQty: string;
266
576
  }
577
+ interface TopOfBookTicker {
578
+ symbol: string;
579
+ bidPrice: number;
580
+ bidQty: number;
581
+ askPrice: number;
582
+ askQty: number;
583
+ timestamp?: number | null;
584
+ }
585
+ interface AggTradesRequest {
586
+ symbol: string;
587
+ startTime: number;
588
+ endTime: number;
589
+ limit?: number;
590
+ }
591
+ interface AggTrade {
592
+ aggregateTradeId: number;
593
+ price: number;
594
+ quantity: number;
595
+ firstTradeId: number;
596
+ lastTradeId: number;
597
+ timestamp: number;
598
+ isBuyerMaker: boolean;
599
+ }
600
+ interface OrderBookDepthRequest {
601
+ symbol: string;
602
+ limit?: 5 | 10 | 20 | 50 | 100 | 500 | 1000 | 5000;
603
+ }
604
+ interface OrderBookDepth {
605
+ symbol: string;
606
+ lastUpdateId: number | null;
607
+ bids: Array<[price: number, quantity: number]>;
608
+ asks: Array<[price: number, quantity: number]>;
609
+ timestamp: number;
610
+ }
267
611
  type TrendLineMode = 'lows' | 'highs';
268
612
  type TrendLine = {
269
613
  id: string;
@@ -317,6 +661,14 @@ interface TrendLineOptions {
317
661
  range?: number;
318
662
  epsilon?: number;
319
663
  epsilonOffset?: number;
664
+ epsilonMode?: 'static' | 'atr';
665
+ epsilonAtrPeriod?: number;
666
+ epsilonAtrMultiplier?: number;
667
+ epsilonOffsetAtrMultiplier?: number;
668
+ epsilonMin?: number;
669
+ epsilonMax?: number;
670
+ epsilonOffsetMin?: number;
671
+ epsilonOffsetMax?: number;
320
672
  minTouches?: number;
321
673
  minDistance?: number;
322
674
  firstRange?: number;
@@ -333,10 +685,19 @@ interface Signal {
333
685
  symbol: string;
334
686
  interval: Interval;
335
687
  strategy: string;
688
+ universe?: MarketUniverse;
689
+ assetClass?: AssetClass;
690
+ accountId?: string;
691
+ deploymentId?: string;
692
+ policyProfileId?: string;
693
+ runtimeConfigId?: string;
336
694
  direction: Direction;
337
695
  timestamp: number;
338
696
  orderStatus?: SignalOrderStatus;
339
697
  orderSkipReason?: string;
698
+ orderFailureReason?: string;
699
+ orderQty?: number;
700
+ orderValue?: number;
340
701
  isConfigFromBacktest?: boolean;
341
702
  aiAnalysis?: Partial<SignalAnalysis>;
342
703
  ml?: {
@@ -365,6 +726,12 @@ interface RuntimeSignalEvaluationRecord {
365
726
  evaluationId: string;
366
727
  userName: string;
367
728
  strategy: string;
729
+ universe?: MarketUniverse;
730
+ assetClass?: AssetClass;
731
+ accountId?: string;
732
+ deploymentId?: string;
733
+ policyProfileId?: string;
734
+ runtimeConfigId?: string;
368
735
  symbol: string;
369
736
  interval: Interval;
370
737
  timestamp: number;
@@ -408,45 +775,171 @@ interface RuntimeAiAnalysisSnapshot {
408
775
  }
409
776
  type SignalOrderStatus = 'completed' | 'failed' | 'skipped' | 'canceled';
410
777
  type RuntimeTradeStatus = 'active' | 'closed';
778
+ type RuntimeTradeExitType = 'exit' | 'tp' | 'sl' | 'unknown';
779
+ type RuntimeTradeFillSource = 'exchange_position' | 'requested_price' | 'unknown';
780
+ type RuntimeTradeTelemetryQuality = 'full' | 'partial' | 'price_only' | 'none';
411
781
  interface RuntimeTradeRecord {
412
782
  orderId: string;
413
783
  signalId?: string;
414
784
  strategy: string;
785
+ universe?: MarketUniverse;
786
+ assetClass?: AssetClass;
787
+ accountId?: string;
788
+ deploymentId?: string;
789
+ policyProfileId?: string;
790
+ runtimeConfigId?: string;
415
791
  symbol: string;
792
+ interval?: Interval;
416
793
  direction: Direction;
417
794
  qty: number;
418
795
  entryPrice: number;
796
+ actualEntryPrice?: number | null;
419
797
  entryTimestamp: number;
798
+ signalTimestamp?: number | null;
799
+ signalClosePrice?: number | null;
800
+ arrivalSnapshotTime?: number | null;
801
+ arrivalSource?: string | null;
802
+ arrivalMid?: number | null;
803
+ bid?: number | null;
804
+ ask?: number | null;
805
+ spreadBps?: number | null;
806
+ orderSubmitTime?: number | null;
807
+ orderAckTime?: number | null;
808
+ fillAvgPrice?: number | null;
809
+ fillSource?: RuntimeTradeFillSource | null;
810
+ fillTime?: number | null;
811
+ telemetryQuality?: RuntimeTradeTelemetryQuality | null;
812
+ fee?: number | null;
420
813
  status: RuntimeTradeStatus;
421
814
  currentPrice?: number | null;
422
815
  currentPnl?: number | null;
423
816
  closedPnl?: number | null;
424
817
  exitPrice?: number | null;
818
+ actualExitPrice?: number | null;
425
819
  exitTimestamp?: number | null;
820
+ exitType?: RuntimeTradeExitType | null;
821
+ openFee?: number | null;
822
+ closeFee?: number | null;
823
+ fundingFee?: number | null;
824
+ totalFee?: number | null;
426
825
  aiAnalysis?: Partial<SignalAnalysis> | null;
427
826
  lastSyncedAt?: number;
428
827
  }
828
+ interface RuntimeStrategyCloseNotification {
829
+ userName?: string;
830
+ strategy: string;
831
+ openedByStrategy: string;
832
+ symbol: string;
833
+ direction: Direction;
834
+ code: string;
835
+ orderId: string;
836
+ signalId?: string;
837
+ qty: number;
838
+ entryPrice: number;
839
+ entryTimestamp: number;
840
+ exitPrice?: number | null;
841
+ exitTimestamp?: number | null;
842
+ closedPnl?: number | null;
843
+ exitType?: RuntimeTradeExitType | null;
844
+ }
429
845
 
430
- type Strategy = (candle: KlineChartItem, btcCandle: KlineChartItem) => Promise<string | Signal>;
431
- type BacktestPriceMode = 'mid' | 'close' | 'open' | 'rand';
846
+ type ExecutionCostSource = 'exchange-account' | 'connector-default' | 'config' | 'historical' | 'calibrated' | 'fallback' | 'disabled' | 'unavailable';
847
+ type ExecutionCostQuality = 'full' | 'partial' | 'fallback';
848
+ interface ExecutionCostModel {
849
+ fees: {
850
+ makerRate: number;
851
+ takerRate: number;
852
+ source: ExecutionCostSource;
853
+ };
854
+ funding: {
855
+ enabled: boolean;
856
+ source: ExecutionCostSource;
857
+ points?: number;
858
+ fromTimestamp?: number | null;
859
+ toTimestamp?: number | null;
860
+ };
861
+ slippage: {
862
+ baseBps: number;
863
+ spreadMultiplier: number;
864
+ marketImpactBps: number;
865
+ delayRiskMultiplier: number;
866
+ source: ExecutionCostSource;
867
+ };
868
+ leverage: {
869
+ requested: number;
870
+ effective: number;
871
+ maxAllowed: number | null;
872
+ };
873
+ quality: ExecutionCostQuality;
874
+ capturedAt: number;
875
+ }
876
+ type Strategy = (candle: KlineChartItem, btcCandle: KlineChartItem, ethCandle?: KlineChartItem) => Promise<string | Signal>;
877
+ type BacktestDetectorOptimizedStrategy = Strategy & {
878
+ detectorFanoutKey?: string;
879
+ detectorNoSignalSkipReason?: string;
880
+ canFastAdvanceDetectorNoSignal?: boolean;
881
+ advanceDetectorNoSignal?: (candle: KlineChartItem, btcCandle: KlineChartItem, code: string) => Promise<string | Signal>;
882
+ skipDetectorNoSignal?: (candle: KlineChartItem, btcCandle: KlineChartItem, code: string) => Promise<string | Signal>;
883
+ };
884
+ type BacktestPriceMode = 'mid' | 'close' | 'open';
432
885
  interface StrategyConfig {
886
+ ENABLE?: boolean;
887
+ INTERVAL?: Interval | string;
888
+ UNIVERSE?: MarketUniverse;
889
+ ACCOUNT_ID?: string;
433
890
  BACKTEST_PRICE_MODE?: BacktestPriceMode;
891
+ BACKTEST_ENTRY_DELAY_BARS?: number;
892
+ BACKTEST_EXECUTION_INTERVAL?: Interval;
893
+ BACKTEST_EXECUTION_DELAY_MS?: number;
434
894
  ML_ENABLED?: boolean;
895
+ POLICY_PROFILE_ID?: string;
896
+ MAKER_FEE_RATE?: number;
897
+ TAKER_FEE_RATE?: number;
898
+ FUNDING_ENABLED?: boolean;
899
+ LEVERAGE?: number;
900
+ SLIPPAGE_BASE_BPS?: number;
901
+ SLIPPAGE_SPREAD_MULTIPLIER?: number;
902
+ SLIPPAGE_MARKET_IMPACT_BPS?: number;
903
+ SLIPPAGE_DELAY_RISK_MULTIPLIER?: number;
904
+ EXECUTION_COSTS_CACHE_ONLY?: boolean;
435
905
  [key: string]: any;
436
906
  }
437
907
  type StrategyResultConfig = StrategyConfig;
438
908
  type StrategyConfigGrid = Record<string, unknown[]>;
439
909
  interface StrategyCreatorParams {
440
910
  userName: string;
911
+ connectorName: string;
441
912
  symbol: string;
913
+ universe?: MarketUniverse;
914
+ assetClass?: AssetClass;
915
+ instrument?: InstrumentDescriptor;
916
+ accountId?: string;
917
+ deploymentId?: string;
918
+ policyProfileId?: string;
919
+ runtimeConfigId?: string;
442
920
  config: StrategyConfig;
443
921
  connector: Connector;
444
922
  data: KlineChartData;
445
923
  btcData: KlineChartData;
924
+ ethData?: KlineChartData;
446
925
  btcBinanceData?: KlineChartData;
447
926
  btcCoinbaseData?: KlineChartData;
927
+ backtestExecutionMarketData?: {
928
+ interval: Interval;
929
+ data: KlineChartData;
930
+ btcData?: KlineChartData;
931
+ dataByTimestamp?: Map<number, KlineChartItem>;
932
+ btcDataByTimestamp?: Map<number, KlineChartItem>;
933
+ };
934
+ sharedIndicatorsReplayKey?: string;
935
+ sharedStrategyStateKey?: string;
936
+ onRuntimeClose?: (event: RuntimeStrategyCloseNotification) => void;
937
+ }
938
+ interface StrategyCreator {
939
+ (params: StrategyCreatorParams): Promise<Strategy>;
940
+ detectorKey?: (config: StrategyConfig) => string | undefined;
941
+ detectorNoSignalSkipReason?: string;
448
942
  }
449
- type StrategyCreator = (params: StrategyCreatorParams) => Promise<Strategy>;
450
943
  type TestingOptions = Pick<KlineRequest, 'start' | 'end'>;
451
944
  interface BacktestRunConfig {
452
945
  strategyName: string;
@@ -458,11 +951,24 @@ interface Test extends BacktestRunConfig {
458
951
  name: string;
459
952
  testId: string;
460
953
  testSuiteId: string;
954
+ configId?: string;
461
955
  symbol: string;
956
+ universe?: MarketUniverse;
957
+ assetClass?: AssetClass;
958
+ instrument?: InstrumentDescriptor;
959
+ accountId?: string;
960
+ deploymentId?: string;
961
+ policyProfileId?: string;
962
+ executionCostModel?: ExecutionCostModel;
963
+ interval?: Interval;
462
964
  options: TestingOptions;
463
965
  ml?: boolean;
464
966
  ai?: boolean;
967
+ fast?: boolean;
968
+ collectReplaySignalEvaluations?: boolean;
465
969
  chunkId?: string;
970
+ backtestRunId?: string;
971
+ backtestTestKey?: string;
466
972
  timeoutMs?: number;
467
973
  }
468
974
  type TestSuite = Test[];
@@ -485,6 +991,7 @@ interface TestingBoxResult {
485
991
  inlineOrderLog?: OrderLogData;
486
992
  inlinePositionLog?: PositionLogData;
487
993
  inlineReplaySignalEvaluations?: RuntimeSignalEvaluationRecord[];
994
+ executionCostModel?: ExecutionCostModel;
488
995
  }
489
996
  type TestingBox = (test: Test) => Promise<TestingBoxResult | null>;
490
997
  interface TestWorkerResult extends TestingBoxResult {
@@ -499,6 +1006,13 @@ type OrderLog = Order & {
499
1006
  amount: number;
500
1007
  fee?: number;
501
1008
  index: number;
1009
+ executionSlippageStage?: 'entry' | 'exit';
1010
+ executionSlippageBps?: number | null;
1011
+ executionBaseSlippageBps?: number | null;
1012
+ executionSpreadBps?: number | null;
1013
+ executionSpreadSlippageBps?: number | null;
1014
+ executionMarketImpactBps?: number | null;
1015
+ executionDelayRiskBps?: number | null;
502
1016
  };
503
1017
  type OrderLogData = OrderLog[];
504
1018
  type SimpleOrderLogData = [number, number][];
@@ -523,15 +1037,58 @@ interface TestConnector extends Connector {
523
1037
  getResult: () => Promise<TestingBoxResult>;
524
1038
  checkTp: (candle: Candle) => Promise<void>;
525
1039
  checkSl: (candle: Candle) => Promise<void>;
526
- drainMlResultsBatch: () => Promise<Array<{
527
- signalId: string;
528
- profit: number;
529
- }>>;
1040
+ checkExits: (candle: Candle) => Promise<void>;
1041
+ drainMlResultsBatch: () => Promise<TestClosedSignalResult[]>;
1042
+ }
1043
+ type TestTradeExitReason = 'take_profit' | 'stop_loss' | 'exit';
1044
+ interface TestTradeResult {
1045
+ signalId: string;
1046
+ direction: Direction;
1047
+ qty: number;
1048
+ closedQty: number;
1049
+ entryTimestamp: number;
1050
+ exitTimestamp: number;
1051
+ exitReason: TestTradeExitReason;
1052
+ requestedEntryPrice: number;
1053
+ entryPrice: number;
1054
+ requestedExitPrice: number | null;
1055
+ exitPrice: number | null;
1056
+ grossProfit: number;
1057
+ netProfit: number;
1058
+ openFee: number;
1059
+ closeFee: number;
1060
+ fundingFee: number | null;
1061
+ totalFee: number;
1062
+ entrySlippagePrice: number;
1063
+ entrySlippageBps: number;
1064
+ entryBaseSlippageBps: number;
1065
+ entrySpreadBps: number;
1066
+ entrySpreadSlippageBps: number;
1067
+ entryMarketImpactBps: number;
1068
+ entryDelayRiskBps: number | null;
1069
+ entrySlippageCost: number;
1070
+ exitSlippagePrice: number | null;
1071
+ exitSlippageBps: number | null;
1072
+ exitBaseSlippageBps: number | null;
1073
+ exitSpreadBps: number | null;
1074
+ exitSpreadSlippageBps: number | null;
1075
+ exitMarketImpactBps: number | null;
1076
+ exitDelayRiskBps: number | null;
1077
+ exitSlippageCost: number;
1078
+ totalSlippageCost: number;
1079
+ }
1080
+ interface TestClosedSignalResult {
1081
+ signalId: string;
1082
+ profit: number;
1083
+ tradeResult?: TestTradeResult;
530
1084
  }
531
1085
  interface TestConnectorContext {
532
1086
  userName?: string;
533
1087
  mlEnabled?: boolean;
534
1088
  aiEnabled?: boolean;
1089
+ fastMode?: boolean;
1090
+ executionCostModel?: ExecutionCostModel;
1091
+ fundingRates?: FundingRatePoint[];
535
1092
  }
536
1093
  type TestConnectorCreator = (connector: Connector, context?: TestConnectorContext) => TestConnector;
537
1094
  type ChartColor = string;
@@ -645,8 +1202,6 @@ interface StrategyAPIEntryParams {
645
1202
  interface StrategyAPIExitParams {
646
1203
  code?: string;
647
1204
  direction: Direction;
648
- price?: number;
649
- timestamp?: number;
650
1205
  }
651
1206
  interface StrategyProtectPlan {
652
1207
  direction: Direction;
@@ -657,15 +1212,14 @@ interface StrategyAPIProtectParams {
657
1212
  code?: string;
658
1213
  protectPlan: StrategyProtectPlan;
659
1214
  }
660
- interface StrategyAPIMarketDataParams {
661
- preloadStart?: number;
662
- backtestPriceMode?: BacktestPriceMode;
1215
+ interface StrategyIndicatorsContext<TIndicators = unknown> {
1216
+ indicators: TIndicators | undefined;
1217
+ baseContext?: BaseStrategyContextSnapshot;
663
1218
  }
664
- interface StrategyMarketSnapshot {
665
- fullData: KlineChartData;
666
- lastCandle: KlineChartItem;
1219
+ interface StrategyDecisionPriceContext {
667
1220
  timestamp: number;
668
1221
  currentPrice: number;
1222
+ candle: Candle;
669
1223
  }
670
1224
  interface MlCandleIndicatorsSnapshot {
671
1225
  candles15m: Candle[];
@@ -677,6 +1231,727 @@ interface MlCandleIndicatorsSnapshot {
677
1231
  btcCandles4h: Candle[];
678
1232
  btcCandles1d: Candle[];
679
1233
  }
1234
+ interface BaseRawIndicatorSnapshot {
1235
+ trend: {
1236
+ maFast: number | null;
1237
+ maMedium: number | null;
1238
+ maSlow: number | null;
1239
+ };
1240
+ volatility: {
1241
+ atr: number | null;
1242
+ atrPct: number | null;
1243
+ bbUpper: number | null;
1244
+ bbMiddle: number | null;
1245
+ bbLower: number | null;
1246
+ bbWidthPct: number | null;
1247
+ };
1248
+ momentum: {
1249
+ macd: number | null;
1250
+ macdSignal: number | null;
1251
+ macdHistogram: number | null;
1252
+ };
1253
+ volume: {
1254
+ volume: number | null;
1255
+ turnover: number | null;
1256
+ obv: number | null;
1257
+ obvSma: number | null;
1258
+ volume1h: number | null;
1259
+ volume24h: number | null;
1260
+ };
1261
+ price: {
1262
+ prevClose: number | null;
1263
+ price1hPct: number | null;
1264
+ price24hPct: number | null;
1265
+ highPrice1h: number | null;
1266
+ lowPrice1h: number | null;
1267
+ highPrice24h: number | null;
1268
+ lowPrice24h: number | null;
1269
+ };
1270
+ levels: {
1271
+ highLevel: number | null;
1272
+ lowLevel: number | null;
1273
+ };
1274
+ crossAsset: {
1275
+ btcCorrelation: number | null;
1276
+ };
1277
+ }
1278
+ interface BaseRegimeContext {
1279
+ trend: {
1280
+ bias: 'bull' | 'bear' | 'neutral';
1281
+ maStackScore: number | null;
1282
+ priceDistanceToMaFastAtr: number | null;
1283
+ priceDistanceToMaSlowAtr: number | null;
1284
+ persistence: number | null;
1285
+ adx?: {
1286
+ adx: number | null;
1287
+ diPlus: number | null;
1288
+ diMinus: number | null;
1289
+ direction: 'bull' | 'bear' | 'neutral' | 'unknown';
1290
+ strength: 'weak' | 'developing' | 'strong' | 'unknown';
1291
+ };
1292
+ maLayers?: {
1293
+ bullishLayerCount: number | null;
1294
+ bearishLayerCount: number | null;
1295
+ stackScore?: number | null;
1296
+ trendState?: 'bull' | 'bear' | 'sideways' | 'unknown';
1297
+ alignment: 'bull' | 'bear' | 'mixed' | 'unknown';
1298
+ fastImpulseBias: 'bull' | 'bear' | 'neutral' | 'unknown';
1299
+ macroBias: 'bull' | 'bear' | 'neutral' | 'unknown';
1300
+ layerConflict: boolean | null;
1301
+ layers: Array<{
1302
+ fastPeriod: number;
1303
+ slowPeriod: number;
1304
+ fast: number | null;
1305
+ slow: number | null;
1306
+ bias: 'bull' | 'bear' | 'neutral' | 'unknown';
1307
+ }>;
1308
+ };
1309
+ contextMa?: {
1310
+ baseline: number | null;
1311
+ upperBoundary: number | null;
1312
+ lowerBoundary: number | null;
1313
+ contextBias: 'bull' | 'bear' | 'neutral' | 'unknown';
1314
+ distanceToBoundaryAtr: number | null;
1315
+ };
1316
+ adaptiveChannel?: {
1317
+ centerline: number | null;
1318
+ upper: number | null;
1319
+ lower: number | null;
1320
+ direction: 'bull' | 'bear' | 'neutral' | 'unknown';
1321
+ regime?: 'bull' | 'bear' | 'neutral' | 'unknown';
1322
+ roof?: number | null;
1323
+ floor?: number | null;
1324
+ flipUp?: boolean | null;
1325
+ flipDown?: boolean | null;
1326
+ halfChannelAtr?: number | null;
1327
+ centerlineSlope: number | null;
1328
+ channelWidthAtr: number | null;
1329
+ pricePositionInChannel: number | null;
1330
+ };
1331
+ trendFollow?: {
1332
+ state: 'bull' | 'bear' | 'neutral' | 'unknown';
1333
+ lastSignalDirection: Direction | null;
1334
+ signalAgeBars: number | null;
1335
+ trailStop: number | null;
1336
+ distanceToTrailStopAtr: number | null;
1337
+ distanceToTrailStopPct: number | null;
1338
+ lastPivotHigh: number | null;
1339
+ lastPivotLow: number | null;
1340
+ breakoutConfirmed: boolean | null;
1341
+ };
1342
+ psar?: {
1343
+ value: number | null;
1344
+ direction: 'bull' | 'bear' | 'unknown';
1345
+ rawBuySignal: boolean | null;
1346
+ rawSellSignal: boolean | null;
1347
+ buySignal: boolean | null;
1348
+ sellSignal: boolean | null;
1349
+ emaFilter: number | null;
1350
+ trendLongOk: boolean | null;
1351
+ trendShortOk: boolean | null;
1352
+ adxOk: boolean | null;
1353
+ candleLongOk: boolean | null;
1354
+ candleShortOk: boolean | null;
1355
+ cooldownOk: boolean | null;
1356
+ barsSinceSignal: number | null;
1357
+ };
1358
+ };
1359
+ volatility: {
1360
+ atrSlope: number | null;
1361
+ atrPctZScore: number | null;
1362
+ bbWidthPct: number | null;
1363
+ compressionScore: number | null;
1364
+ expansionScore: number | null;
1365
+ state: 'compressed' | 'normal' | 'expanded' | 'unknown';
1366
+ percentiles?: {
1367
+ atrPctRank100: number | null;
1368
+ bbWidthRank100: number | null;
1369
+ realizedVolRank100: number | null;
1370
+ rangeExpansionRank20: number | null;
1371
+ };
1372
+ };
1373
+ momentum: {
1374
+ roc1h: number | null;
1375
+ roc4h: number | null;
1376
+ roc1d: number | null;
1377
+ rsi?: number | null;
1378
+ rsiState?: 'oversold' | 'neutral' | 'overbought' | 'unknown';
1379
+ macdHistogramSlope: number | null;
1380
+ bodyStrength: number | null;
1381
+ closeLocationInRange: number | null;
1382
+ upCloseStreak: number | null;
1383
+ downCloseStreak: number | null;
1384
+ };
1385
+ session: {
1386
+ sessionPhase: 'asia' | 'europe' | 'us' | 'off_hours';
1387
+ sessionWindowPhase: 'opening' | 'active' | 'closing' | 'off_hours';
1388
+ isOverlap: boolean;
1389
+ minutesFromSessionOpen: number | null;
1390
+ minutesToSessionClose: number | null;
1391
+ minutesToFundingWindow: number | null;
1392
+ fundingWindowNearby: boolean;
1393
+ dayOfWeekUtc: 1 | 2 | 3 | 4 | 5 | 6 | 7;
1394
+ isWeekdayUtc: boolean;
1395
+ isWeekendUtc: boolean;
1396
+ };
1397
+ memory: {
1398
+ recentFalseBreakoutDensity: number | null;
1399
+ };
1400
+ }
1401
+ interface BaseStructureContext {
1402
+ swing?: {
1403
+ state: 'trend' | 'range' | 'transition' | 'unknown';
1404
+ bias: 'bull' | 'bear' | 'neutral' | 'unknown';
1405
+ higherHighCount: number | null;
1406
+ higherLowCount: number | null;
1407
+ lowerHighCount: number | null;
1408
+ lowerLowCount: number | null;
1409
+ };
1410
+ zones?: {
1411
+ support: {
1412
+ level: number | null;
1413
+ lower: number | null;
1414
+ upper: number | null;
1415
+ touches: number | null;
1416
+ ageBars: number | null;
1417
+ volumeShare: number | null;
1418
+ distanceAtr: number | null;
1419
+ };
1420
+ resistance: {
1421
+ level: number | null;
1422
+ lower: number | null;
1423
+ upper: number | null;
1424
+ touches: number | null;
1425
+ ageBars: number | null;
1426
+ volumeShare: number | null;
1427
+ distanceAtr: number | null;
1428
+ };
1429
+ active: {
1430
+ side: 'support' | 'resistance' | null;
1431
+ priceInZone: boolean | null;
1432
+ };
1433
+ };
1434
+ srZones?: {
1435
+ levels: Array<{
1436
+ level: number;
1437
+ upper: number;
1438
+ lower: number;
1439
+ strength: number;
1440
+ distancePct: number | null;
1441
+ side: 'support' | 'resistance';
1442
+ }>;
1443
+ nearestSupport: {
1444
+ level: number | null;
1445
+ strength: number | null;
1446
+ distanceAtr: number | null;
1447
+ };
1448
+ nearestResistance: {
1449
+ level: number | null;
1450
+ strength: number | null;
1451
+ distanceAtr: number | null;
1452
+ };
1453
+ crossedAbove: boolean | null;
1454
+ crossedBelow: boolean | null;
1455
+ };
1456
+ liquidity?: {
1457
+ sweepState: 'none' | 'swept_high' | 'swept_low' | 'broken_high' | 'broken_low' | 'unknown';
1458
+ side: 'high' | 'low' | null;
1459
+ referenceZoneSide: 'support' | 'resistance' | null;
1460
+ sweepHigh20: boolean | null;
1461
+ sweepLow20: boolean | null;
1462
+ closeBackInsideRange: boolean | null;
1463
+ stopRunDirection: 'up' | 'down' | null;
1464
+ sweepWickPct: number | null;
1465
+ };
1466
+ liquidityZones?: {
1467
+ activeCount: number;
1468
+ nearestSupport: {
1469
+ top: number | null;
1470
+ bottom: number | null;
1471
+ level: number | null;
1472
+ ageBars: number | null;
1473
+ hitCount: number | null;
1474
+ distanceAtr: number | null;
1475
+ };
1476
+ nearestResistance: {
1477
+ top: number | null;
1478
+ bottom: number | null;
1479
+ level: number | null;
1480
+ ageBars: number | null;
1481
+ hitCount: number | null;
1482
+ distanceAtr: number | null;
1483
+ };
1484
+ activeRetestDirection: Direction | null;
1485
+ retestPenetrationPct: number | null;
1486
+ crossedAbove: boolean | null;
1487
+ crossedBelow: boolean | null;
1488
+ };
1489
+ liquidityTails?: {
1490
+ activeCount: number;
1491
+ nearestBuyPressure: {
1492
+ top: number | null;
1493
+ bottom: number | null;
1494
+ mid: number | null;
1495
+ touches: number | null;
1496
+ ageBars: number | null;
1497
+ distanceAtr: number | null;
1498
+ };
1499
+ nearestSellPressure: {
1500
+ top: number | null;
1501
+ bottom: number | null;
1502
+ mid: number | null;
1503
+ touches: number | null;
1504
+ ageBars: number | null;
1505
+ distanceAtr: number | null;
1506
+ };
1507
+ currentTail: {
1508
+ side: 'upper' | 'lower' | null;
1509
+ wickAtr: number | null;
1510
+ wickBodyRatio: number | null;
1511
+ dominance: number | null;
1512
+ };
1513
+ activeRetestDirection: Direction | null;
1514
+ };
1515
+ structureZones?: {
1516
+ state: 'trend' | 'range' | 'transition' | 'unknown';
1517
+ bias: 'bull' | 'bear' | 'neutral' | 'unknown';
1518
+ support: {
1519
+ top: number | null;
1520
+ bottom: number | null;
1521
+ level: number | null;
1522
+ distanceAtr: number | null;
1523
+ };
1524
+ resistance: {
1525
+ top: number | null;
1526
+ bottom: number | null;
1527
+ level: number | null;
1528
+ distanceAtr: number | null;
1529
+ };
1530
+ acceptAboveResistance: boolean | null;
1531
+ acceptBelowSupport: boolean | null;
1532
+ };
1533
+ pivots?: {
1534
+ lastSwingHigh: number | null;
1535
+ lastSwingLow: number | null;
1536
+ barsSinceSwingHigh: number | null;
1537
+ barsSinceSwingLow: number | null;
1538
+ swingAmplitudeAtr: number | null;
1539
+ pivotDensity20: number | null;
1540
+ pivotDensity50: number | null;
1541
+ };
1542
+ acceptance?: {
1543
+ closesAboveHighLevel3: number | null;
1544
+ closesBelowLowLevel3: number | null;
1545
+ failedAcceptanceBars: number | null;
1546
+ acceptanceScore: number | null;
1547
+ breakoutBodyAtr: number | null;
1548
+ };
1549
+ localRange: {
1550
+ rangePosition20: number | null;
1551
+ distanceToHighLevelAtr: number | null;
1552
+ distanceToLowLevelAtr: number | null;
1553
+ breakoutState: 'inside_range' | 'above_high_level' | 'below_low_level' | 'failed_high_breakout' | 'failed_low_breakout' | 'unknown';
1554
+ barsSinceBreakout: number | null;
1555
+ breakoutRetestQuality: number | null;
1556
+ };
1557
+ levels: {
1558
+ highTouchCount20: number | null;
1559
+ lowTouchCount20: number | null;
1560
+ dominantTouchCount20: number | null;
1561
+ };
1562
+ candleQuality: {
1563
+ upperWickPct: number | null;
1564
+ lowerWickPct: number | null;
1565
+ rejectionWickScore: number | null;
1566
+ };
1567
+ }
1568
+ interface BaseMarketTradeFlowContext {
1569
+ source: 'binance_agg_trades';
1570
+ interval: MarketFeatureInterval;
1571
+ asOfTs: number | null;
1572
+ ageMs: number | null;
1573
+ stale: boolean;
1574
+ trades: number | null;
1575
+ buyPressurePct: number | null;
1576
+ buyBaseVolume: number | null;
1577
+ sellBaseVolume: number | null;
1578
+ buyQuoteVolume: number | null;
1579
+ sellQuoteVolume: number | null;
1580
+ netBaseDelta: number | null;
1581
+ netQuoteDelta: number | null;
1582
+ }
1583
+ interface BaseParticipationContext {
1584
+ volume: {
1585
+ volumeRel20: number | null;
1586
+ turnoverRel20: number | null;
1587
+ volumeTrendSlope: number | null;
1588
+ obvSlope: number | null;
1589
+ effortVsResult: number | null;
1590
+ };
1591
+ priceVolumeProfile?: {
1592
+ pointOfControl: number | null;
1593
+ distanceToPointOfControlAtr: number | null;
1594
+ pointOfControlVolumeShare: number | null;
1595
+ priceAbovePointOfControl: boolean | null;
1596
+ nearPointOfControl: boolean | null;
1597
+ };
1598
+ volumeStructure?: {
1599
+ pointOfControl: number | null;
1600
+ pocIndex: number | null;
1601
+ pointOfControlVolumeShare: number | null;
1602
+ pocUpVolumeShare: number | null;
1603
+ pocDownVolumeShare: number | null;
1604
+ totalUpVolumeShare: number | null;
1605
+ totalDownVolumeShare: number | null;
1606
+ priceAbovePointOfControl: boolean | null;
1607
+ distanceToPointOfControlAtr: number | null;
1608
+ rowCount: number;
1609
+ calcBars: number;
1610
+ };
1611
+ delta?: {
1612
+ source?: 'ohlcv_proxy' | 'kline_taker_volume' | 'agg_trades' | 'trades';
1613
+ buyPressurePct: number | null;
1614
+ buyVolume?: number | null;
1615
+ sellVolume?: number | null;
1616
+ netDelta?: number | null;
1617
+ deltaPct?: number | null;
1618
+ signedVolume: number | null;
1619
+ signedVolumeZScore: number | null;
1620
+ deltaSlope: number | null;
1621
+ deltaDivergenceVsPrice: 'bullish' | 'bearish' | 'none' | 'unknown';
1622
+ };
1623
+ tradeFlow?: BaseMarketTradeFlowContext;
1624
+ }
1625
+ interface BaseRelativeContext {
1626
+ benchmark: {
1627
+ maFast: number | null;
1628
+ maSlow: number | null;
1629
+ bias: 'bull' | 'bear' | 'neutral';
1630
+ relativeStrength1h: number | null;
1631
+ relativeStrength4h: number | null;
1632
+ relativeStrength1d: number | null;
1633
+ trendAlignment: 'aligned_bull' | 'aligned_bear' | 'against_benchmark' | 'neutral' | 'unknown';
1634
+ };
1635
+ execution: {
1636
+ venueSpread: number | null;
1637
+ venueSpreadZScore: number | null;
1638
+ };
1639
+ targetVsBtc?: {
1640
+ source: 'aligned_ohlcv';
1641
+ ratioReturn1h: number | null;
1642
+ ratioReturn4h: number | null;
1643
+ ratioReturn24h: number | null;
1644
+ alphaVsBtc1h: number | null;
1645
+ alphaVsBtc4h: number | null;
1646
+ alphaVsBtc24h: number | null;
1647
+ betaToBtc20: number | null;
1648
+ correlationToBtc20: number | null;
1649
+ ratioTrend: 'up' | 'down' | 'flat' | 'unknown';
1650
+ };
1651
+ targetVsEth?: {
1652
+ source: 'aligned_ohlcv';
1653
+ ratioReturn1h: number | null;
1654
+ ratioReturn4h: number | null;
1655
+ ratioReturn24h: number | null;
1656
+ alphaVsEth1h: number | null;
1657
+ alphaVsEth4h: number | null;
1658
+ alphaVsEth24h: number | null;
1659
+ betaToEth20: number | null;
1660
+ correlationToEth20: number | null;
1661
+ ratioTrend: 'up' | 'down' | 'flat' | 'unknown';
1662
+ };
1663
+ marketBreadth?: {
1664
+ source: 'binance_klines';
1665
+ universe: string;
1666
+ interval: MarketFeatureInterval;
1667
+ asOfTs: number | null;
1668
+ ageMs: number | null;
1669
+ stale: boolean;
1670
+ symbolsCount: number | null;
1671
+ advancers: number | null;
1672
+ decliners: number | null;
1673
+ unchanged: number | null;
1674
+ advanceDeclineRatio: number | null;
1675
+ pctAboveMa20: number | null;
1676
+ pctAboveMa50: number | null;
1677
+ equalWeightedReturn: number | null;
1678
+ volumeWeightedReturn: number | null;
1679
+ dispersion: number | null;
1680
+ };
1681
+ btcAltRegime?: {
1682
+ source: 'binance_klines';
1683
+ universe: string;
1684
+ interval: MarketFeatureInterval;
1685
+ asOfTs: number | null;
1686
+ ageMs: number | null;
1687
+ stale: boolean;
1688
+ btcReturn1h: number | null;
1689
+ btcReturn4h: number | null;
1690
+ btcReturn24h: number | null;
1691
+ altBasketReturn1h: number | null;
1692
+ altBasketReturn4h: number | null;
1693
+ altBasketReturn24h: number | null;
1694
+ btcVsAltReturn1h: number | null;
1695
+ btcVsAltReturn4h: number | null;
1696
+ btcVsAltReturn24h: number | null;
1697
+ btcTurnoverShare1h: number | null;
1698
+ btcTurnoverShare24h: number | null;
1699
+ btcTurnoverShareChange24h: number | null;
1700
+ altVolToBtcVol24h: number | null;
1701
+ altDispersion24h: number | null;
1702
+ regime: 'btc_lead' | 'alt_lead' | 'risk_off' | 'risk_on' | 'mixed' | 'neutral' | 'unknown';
1703
+ };
1704
+ cmcGlobal?: {
1705
+ source: 'coinmarketcap_global';
1706
+ interval: '1d';
1707
+ asOfTs: number | null;
1708
+ ageMs: number | null;
1709
+ stale: boolean;
1710
+ totalMarketCapUsd: number | null;
1711
+ totalVolumeUsd: number | null;
1712
+ totalVolumeReportedUsd: number | null;
1713
+ altMarketCapUsd: number | null;
1714
+ altVolumeUsd: number | null;
1715
+ altVolumeReportedUsd: number | null;
1716
+ btcDominancePct: number | null;
1717
+ ethDominancePct: number | null;
1718
+ btcDominanceChange24hPct: number | null;
1719
+ ethDominanceChange24hPct: number | null;
1720
+ altMarketCapChange24hPct: number | null;
1721
+ altVolumeChange24hPct: number | null;
1722
+ activeCryptocurrencies: number | null;
1723
+ activeExchanges: number | null;
1724
+ activeMarketPairs: number | null;
1725
+ altLiquidityRegime: 'alt_friendly' | 'btc_favored' | 'risk_off' | 'neutral' | 'unknown';
1726
+ };
1727
+ cmcReferenceAssets?: {
1728
+ source: 'coinmarketcap_reference_asset';
1729
+ interval: '1d';
1730
+ asOfTs: number | null;
1731
+ ageMs: number | null;
1732
+ stale: boolean;
1733
+ btcMarketCapUsd: number | null;
1734
+ ethMarketCapUsd: number | null;
1735
+ btcVolumeUsd: number | null;
1736
+ ethVolumeUsd: number | null;
1737
+ btcVolumeToMarketCap: number | null;
1738
+ ethVolumeToMarketCap: number | null;
1739
+ ethBtcMarketCapRatio: number | null;
1740
+ ethBtcMarketCapRatioChange24hPct: number | null;
1741
+ ethVsBtcVolumeRatio: number | null;
1742
+ referenceLiquidityRegime: 'btc_led' | 'eth_led' | 'balanced' | 'thin' | 'unknown';
1743
+ };
1744
+ cmcExchangeLiquidity?: {
1745
+ source: 'coinmarketcap_exchange_liquidity';
1746
+ interval: '1d' | '1h';
1747
+ asOfTs: number | null;
1748
+ ageMs: number | null;
1749
+ stale: boolean;
1750
+ exchangesCount: number | null;
1751
+ totalVolumeUsd: number | null;
1752
+ totalVolumeChange24hPct: number | null;
1753
+ binanceVolumeUsd: number | null;
1754
+ binanceVolumeShare: number | null;
1755
+ topExchangeVolumeShare: number | null;
1756
+ liquidityRegime: CmcExchangeLiquidityRegime;
1757
+ };
1758
+ cmcFearGreed?: {
1759
+ source: 'coinmarketcap_fear_greed';
1760
+ interval: '1d';
1761
+ asOfTs: number | null;
1762
+ ageMs: number | null;
1763
+ stale: boolean;
1764
+ value: number | null;
1765
+ valueChange24h: number | null;
1766
+ valueChange7d: number | null;
1767
+ classification: CmcFearGreedClassification;
1768
+ sentimentRegime: CmcFearGreedRegime;
1769
+ };
1770
+ cmcIndexes?: {
1771
+ source: 'coinmarketcap_index';
1772
+ interval: '1d';
1773
+ asOfTs: number | null;
1774
+ ageMs: number | null;
1775
+ stale: boolean;
1776
+ cmc100Value: number | null;
1777
+ cmc100Change24hPct: number | null;
1778
+ cmc100TopConstituentSymbol: string | null;
1779
+ cmc100TopConstituentWeightPct: number | null;
1780
+ cmc20Value: number | null;
1781
+ cmc20Change24hPct: number | null;
1782
+ cmc20TopConstituentSymbol: string | null;
1783
+ cmc20TopConstituentWeightPct: number | null;
1784
+ cmc20ToCmc100Ratio: number | null;
1785
+ cmc20ToCmc100RatioChange24hPct: number | null;
1786
+ indexRegime: 'top20_led' | 'large_cap_led' | 'risk_off' | 'balanced' | 'unknown';
1787
+ };
1788
+ referenceTradeFlow?: {
1789
+ source: 'binance_reference_market';
1790
+ primaryReferenceSymbol: string;
1791
+ referenceSymbols: string[];
1792
+ tradeFlowBySymbol: Record<string, BaseMarketTradeFlowContext>;
1793
+ };
1794
+ }
1795
+ interface BaseMultiTimeframeContext {
1796
+ compact?: boolean;
1797
+ candles: {
1798
+ m15: Candle[];
1799
+ h1: Candle[];
1800
+ h4: Candle[];
1801
+ d1: Candle[];
1802
+ };
1803
+ benchmarkCandles: {
1804
+ m15: Candle[];
1805
+ h1: Candle[];
1806
+ h4: Candle[];
1807
+ d1: Candle[];
1808
+ };
1809
+ summary?: {
1810
+ h1TrendBias: 'bull' | 'bear' | 'neutral' | 'unknown';
1811
+ h4TrendBias: 'bull' | 'bear' | 'neutral' | 'unknown';
1812
+ d1TrendBias: 'bull' | 'bear' | 'neutral' | 'unknown';
1813
+ h1RangePosition: number | null;
1814
+ h4VolatilityState: 'compressed' | 'normal' | 'expanded' | 'unknown';
1815
+ mtfAlignment: 'aligned_bull' | 'aligned_bear' | 'mixed' | 'neutral' | 'unknown';
1816
+ };
1817
+ }
1818
+ type BaseGateFeatureEntryLocation = 'near_support' | 'near_resistance' | 'mid_range' | 'breakout' | 'breakdown' | 'unknown';
1819
+ type BaseGateFeatureScoreKey = 'structure' | 'participation' | 'relative' | 'mtf' | 'execution' | 'derivatives' | 'totalContext';
1820
+ type BaseGateFeatureConfirmation = 'mtf_aligned' | 'volume_expansion' | 'delta_aligned' | 'trade_flow_aligned' | 'reference_trade_flow_aligned' | 'market_breadth_aligned' | 'cmc_alt_liquidity_aligned' | 'cmc_eth_btc_aligned' | 'cmc_exchange_liquidity_aligned' | 'cmc_fear_greed_aligned' | 'cmc_index_aligned' | 'target_vs_btc_aligned' | 'target_vs_eth_aligned' | 'btc_alt_regime_aligned' | 'benchmark_aligned' | 'breakout_confirmed' | 'liquidity_sweep_aligned' | 'derivatives_aligned';
1821
+ type BaseGateFeatureConflict = 'mtf_against' | 'mtf_mixed' | 'benchmark_against' | 'relative_strength_against' | 'market_breadth_against' | 'cmc_alt_liquidity_against' | 'cmc_eth_btc_against' | 'cmc_exchange_liquidity_against' | 'cmc_fear_greed_against' | 'cmc_index_against' | 'target_vs_btc_against' | 'target_vs_eth_against' | 'btc_alt_regime_against' | 'delta_against' | 'trade_flow_against' | 'reference_trade_flow_against' | 'failed_breakout' | 'extreme_volatility' | 'wide_spread' | 'derivatives_against' | 'derivatives_crowded';
1822
+ type BaseGateFeatureRiskLevel = 'low' | 'medium' | 'high' | 'unknown';
1823
+ type BaseGateFeatureApproveBias = 'support' | 'neutral' | 'reject';
1824
+ type BaseGateFeaturePrimaryIssue = 'none' | 'mtf_conflict' | 'weak_structure' | 'weak_participation' | 'bad_execution' | 'market_context_against' | 'extreme_volatility' | 'crowded_derivatives';
1825
+ interface BaseContextGateFeatures {
1826
+ direction: Direction | null;
1827
+ setup?: {
1828
+ riskRatio: number | null;
1829
+ rewardToVolatility: number | null;
1830
+ stopDistanceAtr: number | null;
1831
+ tpDistanceAtr: number | null;
1832
+ entryLocation: BaseGateFeatureEntryLocation;
1833
+ };
1834
+ scores?: Record<BaseGateFeatureScoreKey, number | null>;
1835
+ confirmations?: {
1836
+ count: number;
1837
+ items: BaseGateFeatureConfirmation[];
1838
+ };
1839
+ conflicts?: {
1840
+ count: number;
1841
+ items: BaseGateFeatureConflict[];
1842
+ };
1843
+ risk?: {
1844
+ regimeRisk: BaseGateFeatureRiskLevel;
1845
+ liquidityRisk: BaseGateFeatureRiskLevel;
1846
+ volatilityRisk: BaseGateFeatureRiskLevel;
1847
+ crowdingRisk: BaseGateFeatureRiskLevel;
1848
+ chaseRisk: BaseGateFeatureRiskLevel;
1849
+ };
1850
+ decisionHints?: {
1851
+ approveBias: BaseGateFeatureApproveBias;
1852
+ maxReasonableQuality: 1 | 2 | 3 | 4 | 5;
1853
+ needsExtraConfirmation: boolean;
1854
+ primaryIssue: BaseGateFeaturePrimaryIssue;
1855
+ };
1856
+ mtf?: {
1857
+ alignmentForDirection: 'aligned' | 'against' | 'mixed' | 'neutral' | 'unknown';
1858
+ higherTimeframeConflict: boolean | null;
1859
+ h1TrendBias: 'bull' | 'bear' | 'neutral' | 'unknown';
1860
+ h4TrendBias: 'bull' | 'bear' | 'neutral' | 'unknown';
1861
+ d1TrendBias: 'bull' | 'bear' | 'neutral' | 'unknown';
1862
+ h1RangePosition: number | null;
1863
+ h4VolatilityState: 'compressed' | 'normal' | 'expanded' | 'unknown';
1864
+ };
1865
+ volatility: {
1866
+ state: 'compressed' | 'normal' | 'expanded' | 'unknown';
1867
+ atrPctZScore: number | null;
1868
+ atrPctRankBucket: 'low' | 'normal' | 'high' | 'extreme' | 'unknown';
1869
+ bbWidthRankBucket: 'low' | 'normal' | 'high' | 'extreme' | 'unknown';
1870
+ extremeVolatilityRisk: boolean;
1871
+ compressionBreakoutSupport: boolean;
1872
+ };
1873
+ structure: {
1874
+ breakoutState: BaseStructureContext['localRange']['breakoutState'];
1875
+ rangePositionBucket: 'low' | 'middle' | 'high' | 'unknown';
1876
+ breakoutWithDirection: boolean | null;
1877
+ failedBreakoutForDirection: boolean | null;
1878
+ liquiditySweepForDirection: boolean | null;
1879
+ nearPointOfControl: boolean | null;
1880
+ };
1881
+ participation: {
1882
+ volumeRel20: number | null;
1883
+ volumeBucket: 'thin' | 'normal' | 'elevated' | 'spike' | 'unknown';
1884
+ deltaBias: 'bull' | 'bear' | 'neutral' | 'unknown';
1885
+ deltaAligned: boolean | null;
1886
+ tradeFlowBuyPressurePct: number | null;
1887
+ tradeFlowAligned: boolean | null;
1888
+ referenceTradeFlowBuyPressurePct: number | null;
1889
+ referenceTradeFlowAligned: boolean | null;
1890
+ volumeStructureAligned: boolean | null;
1891
+ };
1892
+ relative: {
1893
+ benchmarkTrendAlignment: BaseRelativeContext['benchmark']['trendAlignment'];
1894
+ benchmarkAligned: boolean | null;
1895
+ benchmarkConflict: boolean;
1896
+ relativeStrength1h: number | null;
1897
+ relativeStrengthBucket: 'strong_against' | 'mild_against' | 'neutral' | 'mild_with' | 'strong_with' | 'unknown';
1898
+ marketBreadthReturn: number | null;
1899
+ marketBreadthAligned: boolean | null;
1900
+ marketBreadthStale: boolean | null;
1901
+ cmcAltLiquidityRegime: 'alt_friendly' | 'btc_favored' | 'risk_off' | 'neutral' | 'unknown';
1902
+ cmcAltLiquidityAligned: boolean | null;
1903
+ cmcAltLiquidityStale: boolean | null;
1904
+ cmcEthBtcReferenceRegime: 'btc_led' | 'eth_led' | 'balanced' | 'thin' | 'unknown';
1905
+ cmcEthBtcAligned: boolean | null;
1906
+ cmcEthBtcStale: boolean | null;
1907
+ cmcExchangeLiquidityRegime: CmcExchangeLiquidityRegime;
1908
+ cmcExchangeLiquidityAligned: boolean | null;
1909
+ cmcExchangeLiquidityStale: boolean | null;
1910
+ cmcExchangeLiquidityVolumeChange24hPct: number | null;
1911
+ cmcFearGreedValue: number | null;
1912
+ cmcFearGreedValueChange24h: number | null;
1913
+ cmcFearGreedRegime: CmcFearGreedRegime;
1914
+ cmcFearGreedAligned: boolean | null;
1915
+ cmcFearGreedStale: boolean | null;
1916
+ cmcIndexRegime: NonNullable<BaseRelativeContext['cmcIndexes']>['indexRegime'];
1917
+ cmcIndexAligned: boolean | null;
1918
+ cmcIndexStale: boolean | null;
1919
+ cmc20ToCmc100RatioChange24hPct: number | null;
1920
+ targetVsBtcRatioReturn24h: number | null;
1921
+ targetVsBtcAlpha24h: number | null;
1922
+ targetVsBtcBeta20: number | null;
1923
+ targetVsBtcCorrelation20: number | null;
1924
+ targetVsBtcRatioTrend: 'up' | 'down' | 'flat' | 'unknown';
1925
+ targetVsBtcAligned: boolean | null;
1926
+ targetVsEthRatioReturn24h: number | null;
1927
+ targetVsEthAlpha24h: number | null;
1928
+ targetVsEthBeta20: number | null;
1929
+ targetVsEthCorrelation20: number | null;
1930
+ targetVsEthRatioTrend: 'up' | 'down' | 'flat' | 'unknown';
1931
+ targetVsEthAligned: boolean | null;
1932
+ btcAltRegime: 'btc_lead' | 'alt_lead' | 'risk_off' | 'risk_on' | 'mixed' | 'neutral' | 'unknown';
1933
+ btcAltRegimeAligned: boolean | null;
1934
+ btcAltRegimeStale: boolean | null;
1935
+ btcVsAltReturn24h: number | null;
1936
+ btcTurnoverShare24h: number | null;
1937
+ };
1938
+ execution: {
1939
+ venueSpreadZScore: number | null;
1940
+ venueSpreadSeverity: 'normal' | 'elevated' | 'wide' | 'unknown';
1941
+ };
1942
+ }
1943
+ interface BaseStrategyContextSnapshot {
1944
+ candle: Candle;
1945
+ prevCandle: Candle | null;
1946
+ raw: BaseRawIndicatorSnapshot;
1947
+ regime: BaseRegimeContext;
1948
+ structure: BaseStructureContext;
1949
+ participation: BaseParticipationContext;
1950
+ relative: BaseRelativeContext;
1951
+ derivatives?: DerivativesContext | null;
1952
+ mtf: BaseMultiTimeframeContext;
1953
+ gateFeatures?: BaseContextGateFeatures;
1954
+ }
680
1955
  interface BaseIndicatorsHistorySnapshot {
681
1956
  maFast?: number[];
682
1957
  maMedium?: number[];
@@ -705,7 +1980,9 @@ interface BaseIndicatorsHistorySnapshot {
705
1980
  correlation?: number[];
706
1981
  spread?: number[];
707
1982
  }
708
- type IndicatorsHistorySnapshot = Record<string, number[] | Candle[]> & BaseIndicatorsHistorySnapshot & Partial<MlCandleIndicatorsSnapshot>;
1983
+ type IndicatorsHistorySnapshot = Record<string, number[] | Candle[]> & BaseIndicatorsHistorySnapshot & Partial<MlCandleIndicatorsSnapshot> & {
1984
+ baseContext?: BaseStrategyContextSnapshot;
1985
+ };
709
1986
  interface IndicatorSnapshot {
710
1987
  maFast: number;
711
1988
  maMedium: number;
@@ -734,6 +2011,7 @@ interface IndicatorSnapshot {
734
2011
  lowLevel: number | null;
735
2012
  correlation: number;
736
2013
  spread: number | null;
2014
+ baseContext?: BaseStrategyContextSnapshot;
737
2015
  }
738
2016
  interface StrategyDirectionalTpSlParams {
739
2017
  price: number;
@@ -760,7 +2038,23 @@ interface StrategyLastTradeControllerParams {
760
2038
  enabled?: boolean;
761
2039
  cooldownMs?: number;
762
2040
  }
763
- interface StrategyAPI {
2041
+ type StrategySharedReplayStateGetter = <TState>(key: string | undefined, createState: () => TState) => TState;
2042
+ interface StrategyStateControllerOptions<TState, TSnapshot = TState> {
2043
+ sharedReplay?: boolean;
2044
+ configKey?: string;
2045
+ monotonic?: boolean;
2046
+ snapshot?: (state: TState) => TSnapshot;
2047
+ hash?: (snapshot: TSnapshot) => string;
2048
+ }
2049
+ interface StrategyStateController<TState, TResult = unknown, TSnapshot = unknown> {
2050
+ get: () => TState;
2051
+ set: (state: TState) => void;
2052
+ update: (fn: (state: TState) => void) => TState;
2053
+ oncePerTimestamp: (timestamp: number, compute: (state: TState) => TResult) => TResult;
2054
+ snapshot: () => TSnapshot;
2055
+ hash: () => string;
2056
+ }
2057
+ interface StrategyAPI<TIndicators = IndicatorsHistorySnapshot | Record<string, unknown>> {
764
2058
  skip: (code: string) => Extract<StrategyDecision, {
765
2059
  kind: 'skip';
766
2060
  }>;
@@ -773,26 +2067,38 @@ interface StrategyAPI {
773
2067
  protect: (params: StrategyAPIProtectParams) => Extract<StrategyDecision, {
774
2068
  kind: 'protect';
775
2069
  }>;
776
- getMarketData: (params?: StrategyAPIMarketDataParams) => Promise<StrategyMarketSnapshot>;
777
- nextIndicators: (candle: KlineChartData[number], btcCandle: KlineChartData[number]) => unknown;
2070
+ getCurrentIndicatorsContext: () => StrategyIndicatorsContext<TIndicators>;
2071
+ getBaseContext: () => BaseStrategyContextSnapshot | undefined;
2072
+ getDecisionPriceContext: () => Promise<StrategyDecisionPriceContext>;
778
2073
  getCurrentPosition: () => ReturnType<Connector['getPosition']>;
779
- isCurrentPositionExists: () => Promise<boolean>;
780
2074
  getDirectionalTpSlPrices: (params: StrategyDirectionalTpSlParams) => StrategyDirectionalTpSlResult;
781
2075
  createLastTradeController: (params?: StrategyLastTradeControllerParams) => StrategyLastTradeController;
2076
+ createStateController: <TState, TResult = unknown, TSnapshot = TState>(key: string, createState: () => TState, options?: StrategyStateControllerOptions<TState, TSnapshot>) => StrategyStateController<TState, TResult, TSnapshot>;
782
2077
  }
783
2078
  interface StrategyIndicatorsState<TNext = unknown, TSnapshot = Record<string, any> | undefined> {
784
2079
  isInitialized: () => boolean;
785
- setCurrentBar: (candle: KlineChartData[number], btcCandle: KlineChartData[number]) => void;
786
- onBar: (candle?: KlineChartData[number], btcCandle?: KlineChartData[number]) => void;
787
- next: (candle: KlineChartData[number], btcCandle: KlineChartData[number]) => TNext;
2080
+ setCurrentBar: (candle: KlineChartData[number], btcCandle: KlineChartData[number], ethCandle?: KlineChartData[number]) => void;
2081
+ updateReferenceData?: (params: {
2082
+ btcBinanceData?: KlineChartData;
2083
+ btcCoinbaseData?: KlineChartData;
2084
+ }) => void;
2085
+ onBar: (candle?: KlineChartData[number], btcCandle?: KlineChartData[number], ethCandle?: KlineChartData[number]) => void;
2086
+ next: (candle: KlineChartData[number], btcCandle: KlineChartData[number], ethCandle?: KlineChartData[number]) => TNext;
788
2087
  ensureInitializedWithCurrentBar: () => {
789
- snapshot: () => TSnapshot;
2088
+ snapshot: (options?: {
2089
+ compact?: boolean;
2090
+ limit?: number;
2091
+ }) => TSnapshot;
790
2092
  };
791
- snapshot: () => TSnapshot;
2093
+ snapshot: (options?: {
2094
+ compact?: boolean;
2095
+ limit?: number;
2096
+ }) => TSnapshot;
792
2097
  latestNumber: <K extends Extract<keyof NonNullable<TSnapshot>, string>>(key: K) => number | undefined;
793
2098
  }
794
2099
  interface StrategyRuntimeMlOptions {
795
2100
  enabled?: boolean;
2101
+ modelKey?: string;
796
2102
  strategyConfig?: StrategyConfig;
797
2103
  mlThreshold?: number;
798
2104
  }
@@ -845,9 +2151,12 @@ interface CreateStrategyCoreParams<TConfig extends StrategyConfig, TIndicatorsSt
845
2151
  connector: Connector;
846
2152
  data: KlineChartData;
847
2153
  btcData: KlineChartData;
2154
+ ethData?: KlineChartData;
848
2155
  loadPineScriptFile: (fileNameOrPath: string, fallback?: string) => string;
849
- strategyApi: StrategyAPI;
2156
+ strategyApi: StrategyAPI<TIndicatorsState extends StrategyIndicatorsState<any, infer TSnapshot> ? TSnapshot : never>;
850
2157
  indicatorsState: TIndicatorsState;
2158
+ sharedReplayKey?: string;
2159
+ getSharedReplayState?: StrategySharedReplayStateGetter;
851
2160
  }
852
2161
  type StrategyCoreRunner = (candle: KlineChartItem, btcCandle: KlineChartItem) => Promise<StrategyDecision> | StrategyDecision;
853
2162
  type CreateStrategyCore<TConfig extends StrategyConfig, TSnapshot extends Record<string, any> | undefined = Record<string, any> | undefined, TNext = unknown> = (params: CreateStrategyCoreParams<TConfig, StrategyIndicatorsState<TNext, TSnapshot>>) => Promise<StrategyCoreRunner> | StrategyCoreRunner;
@@ -948,10 +2257,29 @@ interface StrategyHookCtx {
948
2257
  strategyName: string;
949
2258
  userName: string;
950
2259
  symbol: string;
2260
+ universe?: MarketUniverse;
2261
+ assetClass?: AssetClass;
2262
+ accountId?: string;
2263
+ deploymentId?: string;
2264
+ policyProfileId?: string;
951
2265
  strategyConfig: StrategyConfig;
952
2266
  env: string;
953
2267
  isConfigFromBacktest: boolean;
954
2268
  }
2269
+ interface StrategyPolicyProfile {
2270
+ id: string;
2271
+ appliesTo?: {
2272
+ universes?: readonly MarketUniverse[];
2273
+ assetClasses?: readonly AssetClass[];
2274
+ };
2275
+ marketDataRequirements?: readonly MarketDataCapability[];
2276
+ entryRuntimeDefaults?: {
2277
+ ai?: StrategyRuntimeAiOptions;
2278
+ ml?: StrategyRuntimeMlOptions;
2279
+ };
2280
+ aiAdapter?: StrategyAiAdapter;
2281
+ mlAdapter?: StrategyMlAdapter;
2282
+ }
955
2283
  interface StrategyHookMarketContext {
956
2284
  candle?: KlineChartItem;
957
2285
  btcCandle?: KlineChartItem;
@@ -1062,6 +2390,8 @@ interface StrategyHookAfterPlaceOrderContext {
1062
2390
  }
1063
2391
  interface StrategyManifest {
1064
2392
  name: string;
2393
+ policyProfiles?: readonly StrategyPolicyProfile[];
2394
+ defaultPolicyProfileId?: string;
1065
2395
  entryRuntimeDefaults?: {
1066
2396
  ai?: StrategyRuntimeAiOptions;
1067
2397
  ml?: Pick<StrategyRuntimeMlOptions, 'enabled'>;
@@ -1101,11 +2431,87 @@ interface AiDatasetRow {
1101
2431
  direction: Direction;
1102
2432
  timestamp: number;
1103
2433
  profit: number;
2434
+ tradeResult?: TestTradeResult;
1104
2435
  payload: AiPayload;
1105
2436
  testId?: string;
1106
2437
  testSuiteId?: string;
1107
2438
  testName?: string;
2439
+ configId?: string;
1108
2440
  connectorName?: string;
2441
+ backtestRunId?: string;
2442
+ backtestTestKey?: string;
2443
+ backtestChunkId?: string;
2444
+ }
2445
+
2446
+ type StrategyChartMetricTone = 'default' | 'neutral' | 'success' | 'warning' | 'error';
2447
+ interface StrategyChartMetric {
2448
+ id: string;
2449
+ label: string;
2450
+ value: string;
2451
+ tone?: StrategyChartMetricTone;
2452
+ }
2453
+ interface StrategyChartDetail {
2454
+ id: string;
2455
+ label: string;
2456
+ value: string;
2457
+ tone?: StrategyChartMetricTone;
2458
+ }
2459
+ interface StrategyChartOrder {
2460
+ id: string;
2461
+ symbol?: string;
2462
+ direction?: string | null;
2463
+ timestamp?: number | null;
2464
+ entryTimestamp?: number | null;
2465
+ exitTimestamp?: number | null;
2466
+ exitReason?: string | null;
2467
+ pnl?: number | null;
2468
+ equityBefore?: number | null;
2469
+ equityAfter?: number | null;
2470
+ qty?: number | null;
2471
+ notional?: number | null;
2472
+ requestedEntryPrice?: number | null;
2473
+ entryPrice?: number | null;
2474
+ requestedExitPrice?: number | null;
2475
+ exitPrice?: number | null;
2476
+ openFee?: number | null;
2477
+ closeFee?: number | null;
2478
+ fundingFee?: number | null;
2479
+ totalFee?: number | null;
2480
+ entrySlippageBps?: number | null;
2481
+ entryBaseSlippageBps?: number | null;
2482
+ entrySpreadBps?: number | null;
2483
+ entrySpreadSlippageBps?: number | null;
2484
+ entryMarketImpactBps?: number | null;
2485
+ entryDelayRiskBps?: number | null;
2486
+ exitSlippageBps?: number | null;
2487
+ exitBaseSlippageBps?: number | null;
2488
+ exitSpreadBps?: number | null;
2489
+ exitSpreadSlippageBps?: number | null;
2490
+ exitMarketImpactBps?: number | null;
2491
+ exitDelayRiskBps?: number | null;
2492
+ totalSlippageCost?: number | null;
2493
+ sequence?: number | null;
2494
+ }
2495
+ interface StrategyChartSnapshot {
2496
+ cardId: string;
2497
+ generatedAt: number;
2498
+ strategyName: string;
2499
+ title: string;
2500
+ subtitle?: string;
2501
+ datasetId?: string;
2502
+ symbols: string[];
2503
+ orderLog: SimpleOrderLogData;
2504
+ orders: StrategyChartOrder[];
2505
+ stat?: Partial<TestStat> | null;
2506
+ metrics: StrategyChartMetric[];
2507
+ details?: StrategyChartDetail[];
2508
+ tags?: string[];
2509
+ }
2510
+ interface StrategyChartsSnapshotResponse {
2511
+ mode: 'replay' | 'ai';
2512
+ generatedAt: number;
2513
+ runLabel: string;
2514
+ strategies: StrategyChartSnapshot[];
1109
2515
  }
1110
2516
 
1111
- export type { AIChatHistory, AIChatMessage, AiDatasetRow, AiPayload, AiPromptPair, BacktestPriceMode, BacktestRunConfig, BaseIndicatorsHistorySnapshot, Bot, BotConfig, BotResults, BotStatus, BuildStrategySignalDraft, BuildStrategySignalParams, Candle, ChartColor, ClosedPnlRecord, CompletedTest, Connector, ConnectorConfig, ConnectorCreator, ConnectorPluginDefinition, ConnectorRegistryEntry, CreateStrategyCore, CreateStrategyCoreParams, DerivativesContext, DerivativesContextRiskFlag, DerivativesInterval, DerivativesIntervalContext, DerivativesPressure, DerivativesRow, DerivativesSymbolContext, Direction, EOMPoint, Figure, Filters, GetClosedPnlParams, GetTickers, Indicator, IndicatorPluginComputeParams, IndicatorPluginDefinition, IndicatorPluginEntry, IndicatorPluginFigureRenderer, IndicatorPluginRenderer, IndicatorSnapshot, Indicators, IndicatorsHistorySnapshot, Interval, Item, Items, Kline, KlineChartData, KlineChartItem, KlineRequest, MetricThreshold, Metrics, MinimalStat, MlCandleIndicatorsSnapshot, MonthlyEquityStats, OnChangeCompare, OnChangeFilters, Order, OrderLog, OrderLogData, OrderType, Position, PositionLog, PositionLogData, PositionPnlSnapshot, Provider, RuntimeAiAnalysisSnapshot, RuntimeSignalEvaluationRecord, RuntimeSignalEvaluationStatus, RuntimeTradeRecord, RuntimeTradeStatus, Signal, SignalAnalysis, SignalOrderStatus, SimpleOrderLogData, Sl, SpreadRow, Strategy, StrategyAPI, StrategyAPIEntryParams, StrategyAPIExitParams, StrategyAPIMarketDataParams, StrategyAPIProtectParams, StrategyAdditionalIndicatorsMap, StrategyAiAdapter, StrategyAiMode, StrategyClosePlan, StrategyConfig, StrategyConfigGrid, StrategyCoreRunner, StrategyCreator, StrategyCreatorParams, StrategyDecision, StrategyDirectionalTpSlParams, StrategyDirectionalTpSlResult, StrategyEntryBaseParams, StrategyEntryModelFigures, StrategyEntryOrderPlan, StrategyEntryRuntimeBaseParams, StrategyEntryRuntimeBuilderParams, StrategyEntryRuntimeOptions, StrategyEntrySignalContext, StrategyEntrySignalDecisionBuilderParams, StrategyEntryTakeProfitsParams, StrategyFigureLine, StrategyFigurePoint, StrategyFigurePoints, StrategyFigureZone, StrategyHookAfterAiContext, StrategyHookAfterDecisionContext, StrategyHookAfterPlaceOrderContext, StrategyHookAiContext, StrategyHookAiSkippedReason, StrategyHookBarContext, StrategyHookBeforeCloseContext, StrategyHookBeforeEntryGateContext, StrategyHookBeforePlaceOrderContext, StrategyHookCtx, StrategyHookEnrichContext, StrategyHookEntryContext, StrategyHookErrorContext, StrategyHookErrorPayload, StrategyHookGateResult, StrategyHookInitContext, StrategyHookMarketContext, StrategyHookMlContext, StrategyHookMlSkippedReason, StrategyHookOrderContext, StrategyHookPolicyContext, StrategyHookSkipContext, StrategyHookStage, StrategyIndicatorsMap, StrategyIndicatorsState, StrategyLastTradeController, StrategyLastTradeControllerParams, StrategyManifest, StrategyMarketSnapshot, StrategyMlAdapter, StrategyPluginDefinition, StrategyProtectPlan, StrategyRegistryEntry, StrategyResultConfig, StrategyResultEntry, StrategyResults, StrategyRuntimeAiOptions, StrategyRuntimeMlOptions, StrategySignalMetaParams, StrategySignalPriceParams, Test, TestCompare, TestCompareList, TestConnector, TestConnectorContext, TestConnectorCreator, TestResult, TestStat, TestSuite, TestThresholds, TestThresholdsKey, TestWorkerResult, TestingBox, TestingBoxResult, TestingOptions, ThresholdLevel, Ticker, Tp, Trend, TrendLine, TrendLineMode, TrendLineOptions, UIFilters };
2517
+ export { type AIChatHistory, type AIChatMessage, type AggTrade, type AggTradesRequest, type AiDatasetRow, type AiPayload, type AiPromptPair, type AssetClass, type BacktestDetectorOptimizedStrategy, type BacktestPriceMode, type BacktestRunConfig, type BaseContextGateFeatures, type BaseGateFeatureApproveBias, type BaseGateFeatureConfirmation, type BaseGateFeatureConflict, type BaseGateFeatureEntryLocation, type BaseGateFeaturePrimaryIssue, type BaseGateFeatureRiskLevel, type BaseGateFeatureScoreKey, type BaseIndicatorsHistorySnapshot, type BaseMarketTradeFlowContext, type BaseMultiTimeframeContext, type BaseParticipationContext, type BaseRawIndicatorSnapshot, type BaseRegimeContext, type BaseRelativeContext, type BaseStrategyContextSnapshot, type BaseStructureContext, type Bot, type BotConfig, type BotResults, type BotStatus, type BuildStrategySignalDraft, type BuildStrategySignalParams, type Candle, type ChartColor, type ClosedPnlRecord, type CmcExchangeLiquidityRegime, type CmcFearGreedClassification, type CmcFearGreedRegime, type CompletedTest, type Connector, type ConnectorCapabilities, type ConnectorConfig, type ConnectorCreator, type ConnectorPluginDefinition, type ConnectorRegistryEntry, type CreateStrategyCore, type CreateStrategyCoreParams, DEFAULT_MARKET_UNIVERSE, type DerivativesContext, type DerivativesContextRiskFlag, type DerivativesInterval, type DerivativesIntervalContext, type DerivativesPressure, type DerivativesPriceOiDivergenceType, type DerivativesRow, type DerivativesSymbolContext, type DerivativesTargetDerivedContext, type Direction, type EOMPoint, type ExchangeEntryRecord, type ExecutionCostModel, type ExecutionCostQuality, type ExecutionCostSource, type Figure, type Filters, type FundingRateHistoryRequest, type FundingRatePoint, type GetAggTrades, type GetClosedPnlParams, type GetFundingRateHistory, type GetOrderBookDepth, type GetTickers, type GetTopOfBookTicker, type GetTradingFeeRate, type Indicator, type IndicatorPluginComputeParams, type IndicatorPluginDefinition, type IndicatorPluginEntry, type IndicatorPluginFigureRenderer, type IndicatorPluginRenderer, type IndicatorSnapshot, type Indicators, type IndicatorsHistorySnapshot, type InstrumentDescriptor, type InstrumentKind, type InstrumentQuery, type InstrumentStatus, type Interval, type Item, type Items, type Kline, type KlineChartData, type KlineChartItem, type KlineRequest, type ListInstruments, type MarketBreadthRow, type MarketCmcExchangeLiquidityContextRow, type MarketCmcFearGreedContextRow, type MarketCmcIndexConstituent, type MarketCmcIndexContextRow, type MarketCmcIndexSlug, type MarketDataCapability, type MarketFeatureInterval, type MarketGlobalContextRow, type MarketGlobalContextSource, type MarketKlineEvent, type MarketReferenceAssetContextRow, type MarketTradeFlowRow, type MarketUniverse, type MetricThreshold, type Metrics, type MinimalStat, type MlCandleIndicatorsSnapshot, type MonthlyEquityStats, type OnChangeCompare, type OnChangeFilters, type Order, type OrderBookDepth, type OrderBookDepthRequest, type OrderLog, type OrderLogData, type OrderType, type Position, type PositionLog, type PositionLogData, type PositionPnlSnapshot, type Provider, type RuntimeAiAnalysisSnapshot, type RuntimeDeployment, type RuntimeDeploymentHeartbeat, type RuntimeDeploymentStrategy, type RuntimeSignalEvaluationRecord, type RuntimeSignalEvaluationStatus, type RuntimeStrategyCloseNotification, type RuntimeTradeExitType, type RuntimeTradeFillSource, type RuntimeTradeRecord, type RuntimeTradeStatus, type RuntimeTradeTelemetryQuality, type Signal, type SignalAnalysis, type SignalOrderStatus, type SimpleOrderLogData, type Sl, type SpreadRow, type Strategy, type StrategyAPI, type StrategyAPIEntryParams, type StrategyAPIExitParams, type StrategyAPIProtectParams, type StrategyAdditionalIndicatorsMap, type StrategyAiAdapter, type StrategyAiMode, type StrategyChartDetail, type StrategyChartMetric, type StrategyChartMetricTone, type StrategyChartOrder, type StrategyChartSnapshot, type StrategyChartsSnapshotResponse, type StrategyClosePlan, type StrategyConfig, type StrategyConfigGrid, type StrategyCoreRunner, type StrategyCreator, type StrategyCreatorParams, type StrategyDecision, type StrategyDecisionPriceContext, type StrategyDirectionalTpSlParams, type StrategyDirectionalTpSlResult, type StrategyEntryBaseParams, type StrategyEntryModelFigures, type StrategyEntryOrderPlan, type StrategyEntryRuntimeBaseParams, type StrategyEntryRuntimeBuilderParams, type StrategyEntryRuntimeOptions, type StrategyEntrySignalContext, type StrategyEntrySignalDecisionBuilderParams, type StrategyEntryTakeProfitsParams, type StrategyFigureLine, type StrategyFigurePoint, type StrategyFigurePoints, type StrategyFigureZone, type StrategyHookAfterAiContext, type StrategyHookAfterDecisionContext, type StrategyHookAfterPlaceOrderContext, type StrategyHookAiContext, type StrategyHookAiSkippedReason, type StrategyHookBarContext, type StrategyHookBeforeCloseContext, type StrategyHookBeforeEntryGateContext, type StrategyHookBeforePlaceOrderContext, type StrategyHookCtx, type StrategyHookEnrichContext, type StrategyHookEntryContext, type StrategyHookErrorContext, type StrategyHookErrorPayload, type StrategyHookGateResult, type StrategyHookInitContext, type StrategyHookMarketContext, type StrategyHookMlContext, type StrategyHookMlSkippedReason, type StrategyHookOrderContext, type StrategyHookPolicyContext, type StrategyHookSkipContext, type StrategyHookStage, type StrategyIndicatorsContext, type StrategyIndicatorsMap, type StrategyIndicatorsState, type StrategyLastTradeController, type StrategyLastTradeControllerParams, type StrategyManifest, type StrategyMlAdapter, type StrategyPluginDefinition, type StrategyPolicyProfile, type StrategyProtectPlan, type StrategyRegistryEntry, type StrategyResultConfig, type StrategyResultEntry, type StrategyResults, type StrategyRuntimeAiOptions, type StrategyRuntimeMlOptions, type StrategySharedReplayStateGetter, type StrategySignalMetaParams, type StrategySignalPriceParams, type StrategyStateController, type StrategyStateControllerOptions, type Test, type TestClosedSignalResult, type TestCompare, type TestCompareList, type TestConnector, type TestConnectorContext, type TestConnectorCreator, type TestResult, type TestStat, type TestSuite, type TestThresholds, type TestThresholdsKey, type TestTradeExitReason, type TestTradeResult, type TestWorkerResult, type TestingBox, type TestingBoxResult, type TestingOptions, type ThresholdLevel, type Ticker, type TickerQuery, type TopOfBookTicker, type Tp, type TradingAccountRef, type TradingFeeRate, type Trend, type TrendLine, type TrendLineMode, type TrendLineOptions, type UIFilters, isMarketUniverse, resolveConnectorUniverse };