backtest-kit 5.0.0 → 5.1.0
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/build/index.cjs +583 -121
- package/build/index.mjs +584 -122
- package/package.json +1 -1
- package/types.d.ts +353 -19
package/build/index.cjs
CHANGED
|
@@ -89,6 +89,10 @@ const coreServices$1 = {
|
|
|
89
89
|
actionCoreService: Symbol('actionCoreService'),
|
|
90
90
|
frameCoreService: Symbol('frameCoreService'),
|
|
91
91
|
};
|
|
92
|
+
const metaServices$1 = {
|
|
93
|
+
priceMetaService: Symbol('priceMetaService'),
|
|
94
|
+
timeMetaService: Symbol('timeMetaService'),
|
|
95
|
+
};
|
|
92
96
|
const globalServices$1 = {
|
|
93
97
|
sizingGlobalService: Symbol('sizingGlobalService'),
|
|
94
98
|
riskGlobalService: Symbol('riskGlobalService'),
|
|
@@ -154,6 +158,7 @@ const TYPES = {
|
|
|
154
158
|
...connectionServices$1,
|
|
155
159
|
...schemaServices$1,
|
|
156
160
|
...coreServices$1,
|
|
161
|
+
...metaServices$1,
|
|
157
162
|
...globalServices$1,
|
|
158
163
|
...commandServices$1,
|
|
159
164
|
...logicPrivateServices$1,
|
|
@@ -3558,19 +3563,6 @@ const beginTime = (run) => (...args) => {
|
|
|
3558
3563
|
return fn();
|
|
3559
3564
|
};
|
|
3560
3565
|
|
|
3561
|
-
/**
|
|
3562
|
-
* Retrieves the current timestamp for debugging purposes.
|
|
3563
|
-
* If an execution context is active (e.g., during a backtest), it returns the timestamp from the context to ensure consistency with the simulated time.
|
|
3564
|
-
* Can be empty (undefined) if not called from strategy async context, as it's intended for debugging and not critical for logic.
|
|
3565
|
-
* @return {number | undefined} The current timestamp in milliseconds from the execution context, or undefined if not available.
|
|
3566
|
-
*/
|
|
3567
|
-
const getDebugTimestamp = () => {
|
|
3568
|
-
if (ExecutionContextService.hasContext()) {
|
|
3569
|
-
return bt.executionContextService.context.when.getTime();
|
|
3570
|
-
}
|
|
3571
|
-
return undefined;
|
|
3572
|
-
};
|
|
3573
|
-
|
|
3574
3566
|
const INTERVAL_MINUTES$6 = {
|
|
3575
3567
|
"1m": 1,
|
|
3576
3568
|
"3m": 3,
|
|
@@ -4278,7 +4270,7 @@ const GET_SIGNAL_FN = functoolsKit.trycatch(async (self) => {
|
|
|
4278
4270
|
pendingAt: currentTime, // Для immediate signal оба времени одинаковые
|
|
4279
4271
|
timestamp: currentTime,
|
|
4280
4272
|
_isScheduled: false,
|
|
4281
|
-
_entry: [{ price: signal.priceOpen, cost: signal.cost ?? GLOBAL_CONFIG.CC_POSITION_ENTRY_COST,
|
|
4273
|
+
_entry: [{ price: signal.priceOpen, cost: signal.cost ?? GLOBAL_CONFIG.CC_POSITION_ENTRY_COST, timestamp: currentTime }],
|
|
4282
4274
|
};
|
|
4283
4275
|
// Валидируем сигнал перед возвратом
|
|
4284
4276
|
VALIDATE_SIGNAL_FN(signalRow, currentPrice, false);
|
|
@@ -4302,7 +4294,7 @@ const GET_SIGNAL_FN = functoolsKit.trycatch(async (self) => {
|
|
|
4302
4294
|
pendingAt: SCHEDULED_SIGNAL_PENDING_MOCK, // Временно, обновится при активации
|
|
4303
4295
|
timestamp: currentTime,
|
|
4304
4296
|
_isScheduled: true,
|
|
4305
|
-
_entry: [{ price: signal.priceOpen, cost: signal.cost ?? GLOBAL_CONFIG.CC_POSITION_ENTRY_COST,
|
|
4297
|
+
_entry: [{ price: signal.priceOpen, cost: signal.cost ?? GLOBAL_CONFIG.CC_POSITION_ENTRY_COST, timestamp: currentTime }],
|
|
4306
4298
|
};
|
|
4307
4299
|
// Валидируем сигнал перед возвратом
|
|
4308
4300
|
VALIDATE_SIGNAL_FN(scheduledSignalRow, currentPrice, true);
|
|
@@ -4322,7 +4314,7 @@ const GET_SIGNAL_FN = functoolsKit.trycatch(async (self) => {
|
|
|
4322
4314
|
pendingAt: currentTime, // Для immediate signal оба времени одинаковые
|
|
4323
4315
|
timestamp: currentTime,
|
|
4324
4316
|
_isScheduled: false,
|
|
4325
|
-
_entry: [{ price: currentPrice, cost: signal.cost ?? GLOBAL_CONFIG.CC_POSITION_ENTRY_COST,
|
|
4317
|
+
_entry: [{ price: currentPrice, cost: signal.cost ?? GLOBAL_CONFIG.CC_POSITION_ENTRY_COST, timestamp: currentTime }],
|
|
4326
4318
|
};
|
|
4327
4319
|
// Валидируем сигнал перед возвратом
|
|
4328
4320
|
VALIDATE_SIGNAL_FN(signalRow, currentPrice, false);
|
|
@@ -4392,7 +4384,7 @@ const WAIT_FOR_DISPOSE_FN$1 = async (self) => {
|
|
|
4392
4384
|
self.params.logger.debug("ClientStrategy dispose");
|
|
4393
4385
|
await self.params.onDispose(self.params.execution.context.symbol, self.params.strategyName, self.params.exchangeName, self.params.method.context.frameName, self.params.execution.context.backtest);
|
|
4394
4386
|
};
|
|
4395
|
-
const PARTIAL_PROFIT_FN = (self, signal, percentToClose, currentPrice) => {
|
|
4387
|
+
const PARTIAL_PROFIT_FN = (self, signal, percentToClose, currentPrice, timestamp) => {
|
|
4396
4388
|
// Initialize partial array if not present
|
|
4397
4389
|
if (!signal._partial)
|
|
4398
4390
|
signal._partial = [];
|
|
@@ -4421,7 +4413,7 @@ const PARTIAL_PROFIT_FN = (self, signal, percentToClose, currentPrice) => {
|
|
|
4421
4413
|
entryCountAtClose,
|
|
4422
4414
|
currentPrice,
|
|
4423
4415
|
costBasisAtClose: remainingCostBasis,
|
|
4424
|
-
|
|
4416
|
+
timestamp,
|
|
4425
4417
|
});
|
|
4426
4418
|
self.params.logger.info("PARTIAL_PROFIT_FN executed", {
|
|
4427
4419
|
signalId: signal.id,
|
|
@@ -4431,7 +4423,7 @@ const PARTIAL_PROFIT_FN = (self, signal, percentToClose, currentPrice) => {
|
|
|
4431
4423
|
});
|
|
4432
4424
|
return true;
|
|
4433
4425
|
};
|
|
4434
|
-
const PARTIAL_LOSS_FN = (self, signal, percentToClose, currentPrice) => {
|
|
4426
|
+
const PARTIAL_LOSS_FN = (self, signal, percentToClose, currentPrice, timestamp) => {
|
|
4435
4427
|
// Initialize partial array if not present
|
|
4436
4428
|
if (!signal._partial)
|
|
4437
4429
|
signal._partial = [];
|
|
@@ -4459,7 +4451,7 @@ const PARTIAL_LOSS_FN = (self, signal, percentToClose, currentPrice) => {
|
|
|
4459
4451
|
currentPrice,
|
|
4460
4452
|
entryCountAtClose,
|
|
4461
4453
|
costBasisAtClose: remainingCostBasis,
|
|
4462
|
-
|
|
4454
|
+
timestamp,
|
|
4463
4455
|
});
|
|
4464
4456
|
self.params.logger.warn("PARTIAL_LOSS_FN executed", {
|
|
4465
4457
|
signalId: signal.id,
|
|
@@ -4856,10 +4848,10 @@ const BREAKEVEN_FN = (self, signal, currentPrice) => {
|
|
|
4856
4848
|
});
|
|
4857
4849
|
return true;
|
|
4858
4850
|
};
|
|
4859
|
-
const AVERAGE_BUY_FN = (self, signal, currentPrice, cost = GLOBAL_CONFIG.CC_POSITION_ENTRY_COST) => {
|
|
4851
|
+
const AVERAGE_BUY_FN = (self, signal, currentPrice, timestamp, cost = GLOBAL_CONFIG.CC_POSITION_ENTRY_COST) => {
|
|
4860
4852
|
// Ensure _entry is initialized (handles signals loaded from disk without _entry)
|
|
4861
4853
|
if (!signal._entry || signal._entry.length === 0) {
|
|
4862
|
-
signal._entry = [{ price: signal.priceOpen, cost: GLOBAL_CONFIG.CC_POSITION_ENTRY_COST,
|
|
4854
|
+
signal._entry = [{ price: signal.priceOpen, cost: GLOBAL_CONFIG.CC_POSITION_ENTRY_COST, timestamp }];
|
|
4863
4855
|
}
|
|
4864
4856
|
if (signal.position === "long") {
|
|
4865
4857
|
// LONG: new entry must beat the all-time low — strictly below every prior entry price
|
|
@@ -4889,7 +4881,7 @@ const AVERAGE_BUY_FN = (self, signal, currentPrice, cost = GLOBAL_CONFIG.CC_POSI
|
|
|
4889
4881
|
return false;
|
|
4890
4882
|
}
|
|
4891
4883
|
}
|
|
4892
|
-
signal._entry.push({ price: currentPrice, cost,
|
|
4884
|
+
signal._entry.push({ price: currentPrice, cost, timestamp });
|
|
4893
4885
|
self.params.logger.info("AVERAGE_BUY_FN executed", {
|
|
4894
4886
|
signalId: signal.id,
|
|
4895
4887
|
position: signal.position,
|
|
@@ -6674,16 +6666,16 @@ class ClientStrategy {
|
|
|
6674
6666
|
* // No DCA: [{ price: 43000, cost: 100 }]
|
|
6675
6667
|
* // One DCA: [{ price: 43000, cost: 100 }, { price: 42000, cost: 100 }]
|
|
6676
6668
|
*/
|
|
6677
|
-
async getPositionEntries(symbol) {
|
|
6669
|
+
async getPositionEntries(symbol, timestamp) {
|
|
6678
6670
|
this.params.logger.debug("ClientStrategy getPositionEntries", { symbol });
|
|
6679
6671
|
if (!this._pendingSignal) {
|
|
6680
6672
|
return null;
|
|
6681
6673
|
}
|
|
6682
6674
|
const entries = this._pendingSignal._entry;
|
|
6683
6675
|
if (!entries || entries.length === 0) {
|
|
6684
|
-
return [{ price: this._pendingSignal.priceOpen, cost: GLOBAL_CONFIG.CC_POSITION_ENTRY_COST }];
|
|
6676
|
+
return [{ price: this._pendingSignal.priceOpen, cost: GLOBAL_CONFIG.CC_POSITION_ENTRY_COST, timestamp }];
|
|
6685
6677
|
}
|
|
6686
|
-
return entries.map(({ price, cost }) => ({ price, cost }));
|
|
6678
|
+
return entries.map(({ price, cost, timestamp }) => ({ price, cost, timestamp }));
|
|
6687
6679
|
}
|
|
6688
6680
|
/**
|
|
6689
6681
|
* Performs a single tick of strategy execution.
|
|
@@ -7519,7 +7511,7 @@ class ClientStrategy {
|
|
|
7519
7511
|
* // success3 = false (skipped, would exceed 100%)
|
|
7520
7512
|
* ```
|
|
7521
7513
|
*/
|
|
7522
|
-
async partialProfit(symbol, percentToClose, currentPrice, backtest) {
|
|
7514
|
+
async partialProfit(symbol, percentToClose, currentPrice, backtest, timestamp) {
|
|
7523
7515
|
this.params.logger.debug("ClientStrategy partialProfit", {
|
|
7524
7516
|
symbol,
|
|
7525
7517
|
percentToClose,
|
|
@@ -7583,7 +7575,7 @@ class ClientStrategy {
|
|
|
7583
7575
|
return false;
|
|
7584
7576
|
}
|
|
7585
7577
|
// Execute partial close logic
|
|
7586
|
-
const wasExecuted = PARTIAL_PROFIT_FN(this, this._pendingSignal, percentToClose, currentPrice);
|
|
7578
|
+
const wasExecuted = PARTIAL_PROFIT_FN(this, this._pendingSignal, percentToClose, currentPrice, timestamp);
|
|
7587
7579
|
// If partial was not executed (exceeded 100%), return false without persistence
|
|
7588
7580
|
if (!wasExecuted) {
|
|
7589
7581
|
return false;
|
|
@@ -7702,7 +7694,7 @@ class ClientStrategy {
|
|
|
7702
7694
|
* // success3 = false (skipped, would exceed 100%)
|
|
7703
7695
|
* ```
|
|
7704
7696
|
*/
|
|
7705
|
-
async partialLoss(symbol, percentToClose, currentPrice, backtest) {
|
|
7697
|
+
async partialLoss(symbol, percentToClose, currentPrice, backtest, timestamp) {
|
|
7706
7698
|
this.params.logger.debug("ClientStrategy partialLoss", {
|
|
7707
7699
|
symbol,
|
|
7708
7700
|
percentToClose,
|
|
@@ -7766,7 +7758,7 @@ class ClientStrategy {
|
|
|
7766
7758
|
return false;
|
|
7767
7759
|
}
|
|
7768
7760
|
// Execute partial close logic
|
|
7769
|
-
const wasExecuted = PARTIAL_LOSS_FN(this, this._pendingSignal, percentToClose, currentPrice);
|
|
7761
|
+
const wasExecuted = PARTIAL_LOSS_FN(this, this._pendingSignal, percentToClose, currentPrice, timestamp);
|
|
7770
7762
|
// If partial was not executed (exceeded 100%), return false without persistence
|
|
7771
7763
|
if (!wasExecuted) {
|
|
7772
7764
|
return false;
|
|
@@ -8522,7 +8514,7 @@ class ClientStrategy {
|
|
|
8522
8514
|
* @param backtest - Whether running in backtest mode
|
|
8523
8515
|
* @returns Promise<boolean> - true if entry added, false if rejected by direction check
|
|
8524
8516
|
*/
|
|
8525
|
-
async averageBuy(symbol, currentPrice, backtest, cost = GLOBAL_CONFIG.CC_POSITION_ENTRY_COST) {
|
|
8517
|
+
async averageBuy(symbol, currentPrice, backtest, timestamp, cost = GLOBAL_CONFIG.CC_POSITION_ENTRY_COST) {
|
|
8526
8518
|
this.params.logger.debug("ClientStrategy averageBuy", {
|
|
8527
8519
|
symbol,
|
|
8528
8520
|
currentPrice,
|
|
@@ -8537,7 +8529,7 @@ class ClientStrategy {
|
|
|
8537
8529
|
throw new Error(`ClientStrategy averageBuy: currentPrice must be a positive finite number, got ${currentPrice}`);
|
|
8538
8530
|
}
|
|
8539
8531
|
// Execute averaging logic
|
|
8540
|
-
const result = AVERAGE_BUY_FN(this, this._pendingSignal, currentPrice, cost);
|
|
8532
|
+
const result = AVERAGE_BUY_FN(this, this._pendingSignal, currentPrice, timestamp, cost);
|
|
8541
8533
|
if (!result) {
|
|
8542
8534
|
return false;
|
|
8543
8535
|
}
|
|
@@ -9001,7 +8993,7 @@ const GET_RISK_FN = (dto, backtest, exchangeName, frameName, self) => {
|
|
|
9001
8993
|
* @param backtest - Whether running in backtest mode
|
|
9002
8994
|
* @returns Unique string key for memoization
|
|
9003
8995
|
*/
|
|
9004
|
-
const CREATE_KEY_FN$
|
|
8996
|
+
const CREATE_KEY_FN$o = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
9005
8997
|
const parts = [symbol, strategyName, exchangeName];
|
|
9006
8998
|
if (frameName)
|
|
9007
8999
|
parts.push(frameName);
|
|
@@ -9178,6 +9170,8 @@ class StrategyConnectionService {
|
|
|
9178
9170
|
this.partialConnectionService = inject(TYPES.partialConnectionService);
|
|
9179
9171
|
this.breakevenConnectionService = inject(TYPES.breakevenConnectionService);
|
|
9180
9172
|
this.actionCoreService = inject(TYPES.actionCoreService);
|
|
9173
|
+
this.timeMetaService = inject(TYPES.timeMetaService);
|
|
9174
|
+
this.priceMetaService = inject(TYPES.priceMetaService);
|
|
9181
9175
|
/**
|
|
9182
9176
|
* Retrieves memoized ClientStrategy instance for given symbol-strategy pair with exchange and frame isolation.
|
|
9183
9177
|
*
|
|
@@ -9191,7 +9185,7 @@ class StrategyConnectionService {
|
|
|
9191
9185
|
* @param backtest - Whether running in backtest mode
|
|
9192
9186
|
* @returns Configured ClientStrategy instance
|
|
9193
9187
|
*/
|
|
9194
|
-
this.getStrategy = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
9188
|
+
this.getStrategy = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$o(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
9195
9189
|
const { riskName = "", riskList = [], getSignal, interval, callbacks, } = this.strategySchemaService.get(strategyName);
|
|
9196
9190
|
return new ClientStrategy({
|
|
9197
9191
|
symbol,
|
|
@@ -9278,6 +9272,20 @@ class StrategyConnectionService {
|
|
|
9278
9272
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9279
9273
|
return await strategy.getTotalCostClosed(symbol);
|
|
9280
9274
|
};
|
|
9275
|
+
/**
|
|
9276
|
+
* Returns the effective (DCA-averaged) entry price for the current pending signal.
|
|
9277
|
+
*
|
|
9278
|
+
* This is the harmonic mean of all _entry prices, which is the correct
|
|
9279
|
+
* cost-basis price used in all PNL calculations.
|
|
9280
|
+
* With no DCA entries, equals the original priceOpen.
|
|
9281
|
+
*
|
|
9282
|
+
* Returns null if no pending signal exists.
|
|
9283
|
+
*
|
|
9284
|
+
* @param backtest - Whether running in backtest mode
|
|
9285
|
+
* @param symbol - Trading pair symbol
|
|
9286
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9287
|
+
* @returns Promise resolving to effective entry price or null
|
|
9288
|
+
*/
|
|
9281
9289
|
this.getPositionAveragePrice = async (backtest, symbol, context) => {
|
|
9282
9290
|
this.loggerService.log("strategyConnectionService getPositionAveragePrice", {
|
|
9283
9291
|
symbol,
|
|
@@ -9287,6 +9295,19 @@ class StrategyConnectionService {
|
|
|
9287
9295
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9288
9296
|
return await strategy.getPositionAveragePrice(symbol);
|
|
9289
9297
|
};
|
|
9298
|
+
/**
|
|
9299
|
+
* Returns the number of DCA entries made for the current pending signal.
|
|
9300
|
+
*
|
|
9301
|
+
* 1 = original entry only (no DCA).
|
|
9302
|
+
* Increases by 1 with each successful commitAverageBuy().
|
|
9303
|
+
*
|
|
9304
|
+
* Returns null if no pending signal exists.
|
|
9305
|
+
*
|
|
9306
|
+
* @param backtest - Whether running in backtest mode
|
|
9307
|
+
* @param symbol - Trading pair symbol
|
|
9308
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9309
|
+
* @returns Promise resolving to entry count or null
|
|
9310
|
+
*/
|
|
9290
9311
|
this.getPositionInvestedCount = async (backtest, symbol, context) => {
|
|
9291
9312
|
this.loggerService.log("strategyConnectionService getPositionInvestedCount", {
|
|
9292
9313
|
symbol,
|
|
@@ -9296,6 +9317,19 @@ class StrategyConnectionService {
|
|
|
9296
9317
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9297
9318
|
return await strategy.getPositionInvestedCount(symbol);
|
|
9298
9319
|
};
|
|
9320
|
+
/**
|
|
9321
|
+
* Returns the total invested cost basis in dollars for the current pending signal.
|
|
9322
|
+
*
|
|
9323
|
+
* Equal to entryCount × $100 (COST_BASIS_PER_ENTRY).
|
|
9324
|
+
* 1 entry = $100, 2 entries = $200, etc.
|
|
9325
|
+
*
|
|
9326
|
+
* Returns null if no pending signal exists.
|
|
9327
|
+
*
|
|
9328
|
+
* @param backtest - Whether running in backtest mode
|
|
9329
|
+
* @param symbol - Trading pair symbol
|
|
9330
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9331
|
+
* @returns Promise resolving to total invested cost in dollars or null
|
|
9332
|
+
*/
|
|
9299
9333
|
this.getPositionInvestedCost = async (backtest, symbol, context) => {
|
|
9300
9334
|
this.loggerService.log("strategyConnectionService getPositionInvestedCost", {
|
|
9301
9335
|
symbol,
|
|
@@ -9305,6 +9339,20 @@ class StrategyConnectionService {
|
|
|
9305
9339
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9306
9340
|
return await strategy.getPositionInvestedCost(symbol);
|
|
9307
9341
|
};
|
|
9342
|
+
/**
|
|
9343
|
+
* Returns the unrealized PNL percentage for the current pending signal at currentPrice.
|
|
9344
|
+
*
|
|
9345
|
+
* Accounts for partial closes, DCA entries, slippage and fees
|
|
9346
|
+
* (delegates to toProfitLossDto).
|
|
9347
|
+
*
|
|
9348
|
+
* Returns null if no pending signal exists.
|
|
9349
|
+
*
|
|
9350
|
+
* @param backtest - Whether running in backtest mode
|
|
9351
|
+
* @param symbol - Trading pair symbol
|
|
9352
|
+
* @param currentPrice - Current market price
|
|
9353
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9354
|
+
* @returns Promise resolving to pnlPercentage or null
|
|
9355
|
+
*/
|
|
9308
9356
|
this.getPositionPnlPercent = async (backtest, symbol, currentPrice, context) => {
|
|
9309
9357
|
this.loggerService.log("strategyConnectionService getPositionPnlPercent", {
|
|
9310
9358
|
symbol,
|
|
@@ -9315,6 +9363,20 @@ class StrategyConnectionService {
|
|
|
9315
9363
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9316
9364
|
return await strategy.getPositionPnlPercent(symbol, currentPrice);
|
|
9317
9365
|
};
|
|
9366
|
+
/**
|
|
9367
|
+
* Returns the unrealized PNL in dollars for the current pending signal at currentPrice.
|
|
9368
|
+
*
|
|
9369
|
+
* Calculated as: pnlPercentage / 100 × totalInvestedCost
|
|
9370
|
+
* Accounts for partial closes, DCA entries, slippage and fees.
|
|
9371
|
+
*
|
|
9372
|
+
* Returns null if no pending signal exists.
|
|
9373
|
+
*
|
|
9374
|
+
* @param backtest - Whether running in backtest mode
|
|
9375
|
+
* @param symbol - Trading pair symbol
|
|
9376
|
+
* @param currentPrice - Current market price
|
|
9377
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9378
|
+
* @returns Promise resolving to pnl in dollars or null
|
|
9379
|
+
*/
|
|
9318
9380
|
this.getPositionPnlCost = async (backtest, symbol, currentPrice, context) => {
|
|
9319
9381
|
this.loggerService.log("strategyConnectionService getPositionPnlCost", {
|
|
9320
9382
|
symbol,
|
|
@@ -9325,6 +9387,27 @@ class StrategyConnectionService {
|
|
|
9325
9387
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9326
9388
|
return await strategy.getPositionPnlCost(symbol, currentPrice);
|
|
9327
9389
|
};
|
|
9390
|
+
/**
|
|
9391
|
+
* Returns the list of DCA entry prices for the current pending signal.
|
|
9392
|
+
*
|
|
9393
|
+
* The first element is always the original priceOpen (initial entry).
|
|
9394
|
+
* Each subsequent element is a price added by commitAverageBuy().
|
|
9395
|
+
*
|
|
9396
|
+
* Returns null if no pending signal exists.
|
|
9397
|
+
* Returns a single-element array [priceOpen] if no DCA entries were made.
|
|
9398
|
+
*
|
|
9399
|
+
* @param backtest - Whether running in backtest mode
|
|
9400
|
+
* @param symbol - Trading pair symbol
|
|
9401
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9402
|
+
* @returns Promise resolving to array of entry prices or null
|
|
9403
|
+
*
|
|
9404
|
+
* @example
|
|
9405
|
+
* ```typescript
|
|
9406
|
+
* // No DCA: [43000]
|
|
9407
|
+
* // One DCA: [43000, 42000]
|
|
9408
|
+
* // Two DCA: [43000, 42000, 41500]
|
|
9409
|
+
* ```
|
|
9410
|
+
*/
|
|
9328
9411
|
this.getPositionLevels = async (backtest, symbol, context) => {
|
|
9329
9412
|
this.loggerService.log("strategyConnectionService getPositionLevels", {
|
|
9330
9413
|
symbol,
|
|
@@ -9334,6 +9417,20 @@ class StrategyConnectionService {
|
|
|
9334
9417
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9335
9418
|
return await strategy.getPositionLevels(symbol);
|
|
9336
9419
|
};
|
|
9420
|
+
/**
|
|
9421
|
+
* Returns the list of partial closes for the current pending signal.
|
|
9422
|
+
*
|
|
9423
|
+
* Each entry records a partial profit or loss close event with its type,
|
|
9424
|
+
* percent closed, price at close, cost basis snapshot, and entry count at close.
|
|
9425
|
+
*
|
|
9426
|
+
* Returns null if no pending signal exists.
|
|
9427
|
+
* Returns an empty array if no partial closes have been executed.
|
|
9428
|
+
*
|
|
9429
|
+
* @param backtest - Whether running in backtest mode
|
|
9430
|
+
* @param symbol - Trading pair symbol
|
|
9431
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9432
|
+
* @returns Promise resolving to array of partial close records or null
|
|
9433
|
+
*/
|
|
9337
9434
|
this.getPositionPartials = async (backtest, symbol, context) => {
|
|
9338
9435
|
this.loggerService.log("strategyConnectionService getPositionPartials", {
|
|
9339
9436
|
symbol,
|
|
@@ -9343,6 +9440,27 @@ class StrategyConnectionService {
|
|
|
9343
9440
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9344
9441
|
return await strategy.getPositionPartials(symbol);
|
|
9345
9442
|
};
|
|
9443
|
+
/**
|
|
9444
|
+
* Returns the list of DCA entry prices and costs for the current pending signal.
|
|
9445
|
+
*
|
|
9446
|
+
* Each entry records the price and cost of a single position entry.
|
|
9447
|
+
* The first element is always the original priceOpen (initial entry).
|
|
9448
|
+
* Each subsequent element is an entry added by averageBuy().
|
|
9449
|
+
*
|
|
9450
|
+
* Returns null if no pending signal exists.
|
|
9451
|
+
* Returns a single-element array [{ price: priceOpen, cost }] if no DCA entries were made.
|
|
9452
|
+
*
|
|
9453
|
+
* @param backtest - Whether running in backtest mode
|
|
9454
|
+
* @param symbol - Trading pair symbol
|
|
9455
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9456
|
+
* @returns Promise resolving to array of entry records or null
|
|
9457
|
+
*
|
|
9458
|
+
* @example
|
|
9459
|
+
* ```typescript
|
|
9460
|
+
* // No DCA: [{ price: 43000, cost: 100 }]
|
|
9461
|
+
* // One DCA: [{ price: 43000, cost: 100 }, { price: 42000, cost: 100 }]
|
|
9462
|
+
* ```
|
|
9463
|
+
*/
|
|
9346
9464
|
this.getPositionEntries = async (backtest, symbol, context) => {
|
|
9347
9465
|
this.loggerService.log("strategyConnectionService getPositionEntries", {
|
|
9348
9466
|
symbol,
|
|
@@ -9350,7 +9468,8 @@ class StrategyConnectionService {
|
|
|
9350
9468
|
backtest,
|
|
9351
9469
|
});
|
|
9352
9470
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9353
|
-
|
|
9471
|
+
const timestamp = await this.timeMetaService.getTimestamp(symbol, context, backtest);
|
|
9472
|
+
return await strategy.getPositionEntries(symbol, timestamp);
|
|
9354
9473
|
};
|
|
9355
9474
|
/**
|
|
9356
9475
|
* Retrieves the currently active scheduled signal for the strategy.
|
|
@@ -9452,6 +9571,10 @@ class StrategyConnectionService {
|
|
|
9452
9571
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9453
9572
|
await strategy.waitForInit();
|
|
9454
9573
|
const tick = await strategy.tick(symbol, context.strategyName);
|
|
9574
|
+
{
|
|
9575
|
+
this.priceMetaService.next(symbol, tick.currentPrice, context, backtest);
|
|
9576
|
+
this.timeMetaService.next(symbol, tick.createdAt, context, backtest);
|
|
9577
|
+
}
|
|
9455
9578
|
{
|
|
9456
9579
|
await CALL_SIGNAL_EMIT_FN(this, tick, context, backtest, symbol);
|
|
9457
9580
|
}
|
|
@@ -9558,7 +9681,7 @@ class StrategyConnectionService {
|
|
|
9558
9681
|
}
|
|
9559
9682
|
return;
|
|
9560
9683
|
}
|
|
9561
|
-
const key = CREATE_KEY_FN$
|
|
9684
|
+
const key = CREATE_KEY_FN$o(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
9562
9685
|
if (!this.getStrategy.has(key)) {
|
|
9563
9686
|
return;
|
|
9564
9687
|
}
|
|
@@ -9627,9 +9750,9 @@ class StrategyConnectionService {
|
|
|
9627
9750
|
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9628
9751
|
* @returns Promise<boolean> - true if `partialProfit` would execute, false otherwise
|
|
9629
9752
|
*/
|
|
9630
|
-
this.validatePartialProfit = (backtest, symbol, percentToClose, currentPrice, context) => {
|
|
9753
|
+
this.validatePartialProfit = async (backtest, symbol, percentToClose, currentPrice, context) => {
|
|
9631
9754
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9632
|
-
return
|
|
9755
|
+
return await strategy.validatePartialProfit(symbol, percentToClose, currentPrice);
|
|
9633
9756
|
};
|
|
9634
9757
|
/**
|
|
9635
9758
|
* Executes partial close at profit level (moving toward TP).
|
|
@@ -9670,7 +9793,8 @@ class StrategyConnectionService {
|
|
|
9670
9793
|
backtest,
|
|
9671
9794
|
});
|
|
9672
9795
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9673
|
-
|
|
9796
|
+
const timestamp = await this.timeMetaService.getTimestamp(symbol, context, backtest);
|
|
9797
|
+
return await strategy.partialProfit(symbol, percentToClose, currentPrice, backtest, timestamp);
|
|
9674
9798
|
};
|
|
9675
9799
|
/**
|
|
9676
9800
|
* Checks whether `partialLoss` would succeed without executing it.
|
|
@@ -9683,9 +9807,9 @@ class StrategyConnectionService {
|
|
|
9683
9807
|
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9684
9808
|
* @returns Promise<boolean> - true if `partialLoss` would execute, false otherwise
|
|
9685
9809
|
*/
|
|
9686
|
-
this.validatePartialLoss = (backtest, symbol, percentToClose, currentPrice, context) => {
|
|
9810
|
+
this.validatePartialLoss = async (backtest, symbol, percentToClose, currentPrice, context) => {
|
|
9687
9811
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9688
|
-
return
|
|
9812
|
+
return await strategy.validatePartialLoss(symbol, percentToClose, currentPrice);
|
|
9689
9813
|
};
|
|
9690
9814
|
/**
|
|
9691
9815
|
* Executes partial close at loss level (moving toward SL).
|
|
@@ -9726,7 +9850,8 @@ class StrategyConnectionService {
|
|
|
9726
9850
|
backtest,
|
|
9727
9851
|
});
|
|
9728
9852
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9729
|
-
|
|
9853
|
+
const timestamp = await this.timeMetaService.getTimestamp(symbol, context, backtest);
|
|
9854
|
+
return await strategy.partialLoss(symbol, percentToClose, currentPrice, backtest, timestamp);
|
|
9730
9855
|
};
|
|
9731
9856
|
/**
|
|
9732
9857
|
* Checks whether `trailingStop` would succeed without executing it.
|
|
@@ -9739,9 +9864,9 @@ class StrategyConnectionService {
|
|
|
9739
9864
|
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9740
9865
|
* @returns Promise<boolean> - true if `trailingStop` would execute, false otherwise
|
|
9741
9866
|
*/
|
|
9742
|
-
this.validateTrailingStop = (backtest, symbol, percentShift, currentPrice, context) => {
|
|
9867
|
+
this.validateTrailingStop = async (backtest, symbol, percentShift, currentPrice, context) => {
|
|
9743
9868
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9744
|
-
return
|
|
9869
|
+
return await strategy.validateTrailingStop(symbol, percentShift, currentPrice);
|
|
9745
9870
|
};
|
|
9746
9871
|
/**
|
|
9747
9872
|
* Adjusts the trailing stop-loss distance for an active pending signal.
|
|
@@ -9793,9 +9918,9 @@ class StrategyConnectionService {
|
|
|
9793
9918
|
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9794
9919
|
* @returns Promise<boolean> - true if `trailingTake` would execute, false otherwise
|
|
9795
9920
|
*/
|
|
9796
|
-
this.validateTrailingTake = (backtest, symbol, percentShift, currentPrice, context) => {
|
|
9921
|
+
this.validateTrailingTake = async (backtest, symbol, percentShift, currentPrice, context) => {
|
|
9797
9922
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9798
|
-
return
|
|
9923
|
+
return await strategy.validateTrailingTake(symbol, percentShift, currentPrice);
|
|
9799
9924
|
};
|
|
9800
9925
|
/**
|
|
9801
9926
|
* Adjusts the trailing take-profit distance for an active pending signal.
|
|
@@ -9846,9 +9971,9 @@ class StrategyConnectionService {
|
|
|
9846
9971
|
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9847
9972
|
* @returns Promise<boolean> - true if `breakeven` would execute, false otherwise
|
|
9848
9973
|
*/
|
|
9849
|
-
this.validateBreakeven = (backtest, symbol, currentPrice, context) => {
|
|
9974
|
+
this.validateBreakeven = async (backtest, symbol, currentPrice, context) => {
|
|
9850
9975
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9851
|
-
return
|
|
9976
|
+
return await strategy.validateBreakeven(symbol, currentPrice);
|
|
9852
9977
|
};
|
|
9853
9978
|
/**
|
|
9854
9979
|
* Delegates to ClientStrategy.breakeven() with current execution context.
|
|
@@ -9925,9 +10050,9 @@ class StrategyConnectionService {
|
|
|
9925
10050
|
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9926
10051
|
* @returns Promise<boolean> - true if `averageBuy` would execute, false otherwise
|
|
9927
10052
|
*/
|
|
9928
|
-
this.validateAverageBuy = (backtest, symbol, currentPrice, context) => {
|
|
10053
|
+
this.validateAverageBuy = async (backtest, symbol, currentPrice, context) => {
|
|
9929
10054
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9930
|
-
return
|
|
10055
|
+
return await strategy.validateAverageBuy(symbol, currentPrice);
|
|
9931
10056
|
};
|
|
9932
10057
|
/**
|
|
9933
10058
|
* Adds a new DCA entry to the active pending signal.
|
|
@@ -9948,7 +10073,8 @@ class StrategyConnectionService {
|
|
|
9948
10073
|
backtest,
|
|
9949
10074
|
});
|
|
9950
10075
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9951
|
-
|
|
10076
|
+
const timestamp = await this.timeMetaService.getTimestamp(symbol, context, backtest);
|
|
10077
|
+
return await strategy.averageBuy(symbol, currentPrice, backtest, timestamp, cost);
|
|
9952
10078
|
};
|
|
9953
10079
|
}
|
|
9954
10080
|
}
|
|
@@ -10689,7 +10815,7 @@ class ClientRisk {
|
|
|
10689
10815
|
* @param backtest - Whether running in backtest mode
|
|
10690
10816
|
* @returns Unique string key for memoization
|
|
10691
10817
|
*/
|
|
10692
|
-
const CREATE_KEY_FN$
|
|
10818
|
+
const CREATE_KEY_FN$n = (riskName, exchangeName, frameName, backtest) => {
|
|
10693
10819
|
const parts = [riskName, exchangeName];
|
|
10694
10820
|
if (frameName)
|
|
10695
10821
|
parts.push(frameName);
|
|
@@ -10788,7 +10914,7 @@ class RiskConnectionService {
|
|
|
10788
10914
|
* @param backtest - True if backtest mode, false if live mode
|
|
10789
10915
|
* @returns Configured ClientRisk instance
|
|
10790
10916
|
*/
|
|
10791
|
-
this.getRisk = functoolsKit.memoize(([riskName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
10917
|
+
this.getRisk = functoolsKit.memoize(([riskName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$n(riskName, exchangeName, frameName, backtest), (riskName, exchangeName, frameName, backtest) => {
|
|
10792
10918
|
const schema = this.riskSchemaService.get(riskName);
|
|
10793
10919
|
return new ClientRisk({
|
|
10794
10920
|
...schema,
|
|
@@ -10856,7 +10982,7 @@ class RiskConnectionService {
|
|
|
10856
10982
|
payload,
|
|
10857
10983
|
});
|
|
10858
10984
|
if (payload) {
|
|
10859
|
-
const key = CREATE_KEY_FN$
|
|
10985
|
+
const key = CREATE_KEY_FN$n(payload.riskName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
10860
10986
|
this.getRisk.clear(key);
|
|
10861
10987
|
}
|
|
10862
10988
|
else {
|
|
@@ -12323,7 +12449,7 @@ class ClientAction {
|
|
|
12323
12449
|
* @param backtest - Whether running in backtest mode
|
|
12324
12450
|
* @returns Unique string key for memoization
|
|
12325
12451
|
*/
|
|
12326
|
-
const CREATE_KEY_FN$
|
|
12452
|
+
const CREATE_KEY_FN$m = (actionName, strategyName, exchangeName, frameName, backtest) => {
|
|
12327
12453
|
const parts = [actionName, strategyName, exchangeName];
|
|
12328
12454
|
if (frameName)
|
|
12329
12455
|
parts.push(frameName);
|
|
@@ -12374,7 +12500,7 @@ class ActionConnectionService {
|
|
|
12374
12500
|
* @param backtest - True if backtest mode, false if live mode
|
|
12375
12501
|
* @returns Configured ClientAction instance
|
|
12376
12502
|
*/
|
|
12377
|
-
this.getAction = functoolsKit.memoize(([actionName, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
12503
|
+
this.getAction = functoolsKit.memoize(([actionName, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$m(actionName, strategyName, exchangeName, frameName, backtest), (actionName, strategyName, exchangeName, frameName, backtest) => {
|
|
12378
12504
|
const schema = this.actionSchemaService.get(actionName);
|
|
12379
12505
|
return new ClientAction({
|
|
12380
12506
|
...schema,
|
|
@@ -12584,7 +12710,7 @@ class ActionConnectionService {
|
|
|
12584
12710
|
await Promise.all(actions.map(async (action) => await action.dispose()));
|
|
12585
12711
|
return;
|
|
12586
12712
|
}
|
|
12587
|
-
const key = CREATE_KEY_FN$
|
|
12713
|
+
const key = CREATE_KEY_FN$m(payload.actionName, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
12588
12714
|
if (!this.getAction.has(key)) {
|
|
12589
12715
|
return;
|
|
12590
12716
|
}
|
|
@@ -12602,7 +12728,7 @@ const METHOD_NAME_VALIDATE$2 = "exchangeCoreService validate";
|
|
|
12602
12728
|
* @param exchangeName - Exchange name
|
|
12603
12729
|
* @returns Unique string key for memoization
|
|
12604
12730
|
*/
|
|
12605
|
-
const CREATE_KEY_FN$
|
|
12731
|
+
const CREATE_KEY_FN$l = (exchangeName) => {
|
|
12606
12732
|
return exchangeName;
|
|
12607
12733
|
};
|
|
12608
12734
|
/**
|
|
@@ -12626,7 +12752,7 @@ class ExchangeCoreService {
|
|
|
12626
12752
|
* @param exchangeName - Name of the exchange to validate
|
|
12627
12753
|
* @returns Promise that resolves when validation is complete
|
|
12628
12754
|
*/
|
|
12629
|
-
this.validate = functoolsKit.memoize(([exchangeName]) => CREATE_KEY_FN$
|
|
12755
|
+
this.validate = functoolsKit.memoize(([exchangeName]) => CREATE_KEY_FN$l(exchangeName), async (exchangeName) => {
|
|
12630
12756
|
this.loggerService.log(METHOD_NAME_VALIDATE$2, {
|
|
12631
12757
|
exchangeName,
|
|
12632
12758
|
});
|
|
@@ -12878,7 +13004,7 @@ const METHOD_NAME_VALIDATE$1 = "strategyCoreService validate";
|
|
|
12878
13004
|
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
12879
13005
|
* @returns Unique string key for memoization
|
|
12880
13006
|
*/
|
|
12881
|
-
const CREATE_KEY_FN$
|
|
13007
|
+
const CREATE_KEY_FN$k = (context) => {
|
|
12882
13008
|
const parts = [context.strategyName, context.exchangeName];
|
|
12883
13009
|
if (context.frameName)
|
|
12884
13010
|
parts.push(context.frameName);
|
|
@@ -12910,7 +13036,7 @@ class StrategyCoreService {
|
|
|
12910
13036
|
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
12911
13037
|
* @returns Promise that resolves when validation is complete
|
|
12912
13038
|
*/
|
|
12913
|
-
this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$
|
|
13039
|
+
this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$k(context), async (context) => {
|
|
12914
13040
|
this.loggerService.log(METHOD_NAME_VALIDATE$1, {
|
|
12915
13041
|
context,
|
|
12916
13042
|
});
|
|
@@ -13745,7 +13871,7 @@ class SizingGlobalService {
|
|
|
13745
13871
|
* @param context - Context with riskName, exchangeName, frameName
|
|
13746
13872
|
* @returns Unique string key for memoization
|
|
13747
13873
|
*/
|
|
13748
|
-
const CREATE_KEY_FN$
|
|
13874
|
+
const CREATE_KEY_FN$j = (context) => {
|
|
13749
13875
|
const parts = [context.riskName, context.exchangeName];
|
|
13750
13876
|
if (context.frameName)
|
|
13751
13877
|
parts.push(context.frameName);
|
|
@@ -13771,7 +13897,7 @@ class RiskGlobalService {
|
|
|
13771
13897
|
* @param payload - Payload with riskName, exchangeName and frameName
|
|
13772
13898
|
* @returns Promise that resolves when validation is complete
|
|
13773
13899
|
*/
|
|
13774
|
-
this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$
|
|
13900
|
+
this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$j(context), async (context) => {
|
|
13775
13901
|
this.loggerService.log("riskGlobalService validate", {
|
|
13776
13902
|
context,
|
|
13777
13903
|
});
|
|
@@ -13849,7 +13975,7 @@ const METHOD_NAME_VALIDATE = "actionCoreService validate";
|
|
|
13849
13975
|
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
13850
13976
|
* @returns Unique string key for memoization
|
|
13851
13977
|
*/
|
|
13852
|
-
const CREATE_KEY_FN$
|
|
13978
|
+
const CREATE_KEY_FN$i = (context) => {
|
|
13853
13979
|
const parts = [context.strategyName, context.exchangeName];
|
|
13854
13980
|
if (context.frameName)
|
|
13855
13981
|
parts.push(context.frameName);
|
|
@@ -13893,7 +14019,7 @@ class ActionCoreService {
|
|
|
13893
14019
|
* @param context - Strategy execution context with strategyName, exchangeName and frameName
|
|
13894
14020
|
* @returns Promise that resolves when all validations complete
|
|
13895
14021
|
*/
|
|
13896
|
-
this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$
|
|
14022
|
+
this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$i(context), async (context) => {
|
|
13897
14023
|
this.loggerService.log(METHOD_NAME_VALIDATE, {
|
|
13898
14024
|
context,
|
|
13899
14025
|
});
|
|
@@ -18428,7 +18554,7 @@ const Markdown = new MarkdownAdapter();
|
|
|
18428
18554
|
* @param backtest - Whether running in backtest mode
|
|
18429
18555
|
* @returns Unique string key for memoization
|
|
18430
18556
|
*/
|
|
18431
|
-
const CREATE_KEY_FN$
|
|
18557
|
+
const CREATE_KEY_FN$h = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
18432
18558
|
const parts = [symbol, strategyName, exchangeName];
|
|
18433
18559
|
if (frameName)
|
|
18434
18560
|
parts.push(frameName);
|
|
@@ -18667,7 +18793,7 @@ class BacktestMarkdownService {
|
|
|
18667
18793
|
* Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
18668
18794
|
* Each combination gets its own isolated storage instance.
|
|
18669
18795
|
*/
|
|
18670
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
18796
|
+
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$h(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new ReportStorage$8(symbol, strategyName, exchangeName, frameName));
|
|
18671
18797
|
/**
|
|
18672
18798
|
* Processes tick events and accumulates closed signals.
|
|
18673
18799
|
* Should be called from IStrategyCallbacks.onTick.
|
|
@@ -18824,7 +18950,7 @@ class BacktestMarkdownService {
|
|
|
18824
18950
|
payload,
|
|
18825
18951
|
});
|
|
18826
18952
|
if (payload) {
|
|
18827
|
-
const key = CREATE_KEY_FN$
|
|
18953
|
+
const key = CREATE_KEY_FN$h(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
18828
18954
|
this.getStorage.clear(key);
|
|
18829
18955
|
}
|
|
18830
18956
|
else {
|
|
@@ -18886,7 +19012,7 @@ class BacktestMarkdownService {
|
|
|
18886
19012
|
* @param backtest - Whether running in backtest mode
|
|
18887
19013
|
* @returns Unique string key for memoization
|
|
18888
19014
|
*/
|
|
18889
|
-
const CREATE_KEY_FN$
|
|
19015
|
+
const CREATE_KEY_FN$g = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
18890
19016
|
const parts = [symbol, strategyName, exchangeName];
|
|
18891
19017
|
if (frameName)
|
|
18892
19018
|
parts.push(frameName);
|
|
@@ -19369,7 +19495,7 @@ class LiveMarkdownService {
|
|
|
19369
19495
|
* Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
19370
19496
|
* Each combination gets its own isolated storage instance.
|
|
19371
19497
|
*/
|
|
19372
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
19498
|
+
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$g(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new ReportStorage$7(symbol, strategyName, exchangeName, frameName));
|
|
19373
19499
|
/**
|
|
19374
19500
|
* Subscribes to live signal emitter to receive tick events.
|
|
19375
19501
|
* Protected against multiple subscriptions.
|
|
@@ -19587,7 +19713,7 @@ class LiveMarkdownService {
|
|
|
19587
19713
|
payload,
|
|
19588
19714
|
});
|
|
19589
19715
|
if (payload) {
|
|
19590
|
-
const key = CREATE_KEY_FN$
|
|
19716
|
+
const key = CREATE_KEY_FN$g(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
19591
19717
|
this.getStorage.clear(key);
|
|
19592
19718
|
}
|
|
19593
19719
|
else {
|
|
@@ -19607,7 +19733,7 @@ class LiveMarkdownService {
|
|
|
19607
19733
|
* @param backtest - Whether running in backtest mode
|
|
19608
19734
|
* @returns Unique string key for memoization
|
|
19609
19735
|
*/
|
|
19610
|
-
const CREATE_KEY_FN$
|
|
19736
|
+
const CREATE_KEY_FN$f = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
19611
19737
|
const parts = [symbol, strategyName, exchangeName];
|
|
19612
19738
|
if (frameName)
|
|
19613
19739
|
parts.push(frameName);
|
|
@@ -19898,7 +20024,7 @@ class ScheduleMarkdownService {
|
|
|
19898
20024
|
* Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
19899
20025
|
* Each combination gets its own isolated storage instance.
|
|
19900
20026
|
*/
|
|
19901
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
20027
|
+
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$f(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new ReportStorage$6(symbol, strategyName, exchangeName, frameName));
|
|
19902
20028
|
/**
|
|
19903
20029
|
* Subscribes to signal emitter to receive scheduled signal events.
|
|
19904
20030
|
* Protected against multiple subscriptions.
|
|
@@ -20101,7 +20227,7 @@ class ScheduleMarkdownService {
|
|
|
20101
20227
|
payload,
|
|
20102
20228
|
});
|
|
20103
20229
|
if (payload) {
|
|
20104
|
-
const key = CREATE_KEY_FN$
|
|
20230
|
+
const key = CREATE_KEY_FN$f(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
20105
20231
|
this.getStorage.clear(key);
|
|
20106
20232
|
}
|
|
20107
20233
|
else {
|
|
@@ -20121,7 +20247,7 @@ class ScheduleMarkdownService {
|
|
|
20121
20247
|
* @param backtest - Whether running in backtest mode
|
|
20122
20248
|
* @returns Unique string key for memoization
|
|
20123
20249
|
*/
|
|
20124
|
-
const CREATE_KEY_FN$
|
|
20250
|
+
const CREATE_KEY_FN$e = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
20125
20251
|
const parts = [symbol, strategyName, exchangeName];
|
|
20126
20252
|
if (frameName)
|
|
20127
20253
|
parts.push(frameName);
|
|
@@ -20369,7 +20495,7 @@ class PerformanceMarkdownService {
|
|
|
20369
20495
|
* Memoized function to get or create PerformanceStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
20370
20496
|
* Each combination gets its own isolated storage instance.
|
|
20371
20497
|
*/
|
|
20372
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
20498
|
+
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$e(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new PerformanceStorage(symbol, strategyName, exchangeName, frameName));
|
|
20373
20499
|
/**
|
|
20374
20500
|
* Subscribes to performance emitter to receive performance events.
|
|
20375
20501
|
* Protected against multiple subscriptions.
|
|
@@ -20536,7 +20662,7 @@ class PerformanceMarkdownService {
|
|
|
20536
20662
|
payload,
|
|
20537
20663
|
});
|
|
20538
20664
|
if (payload) {
|
|
20539
|
-
const key = CREATE_KEY_FN$
|
|
20665
|
+
const key = CREATE_KEY_FN$e(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
20540
20666
|
this.getStorage.clear(key);
|
|
20541
20667
|
}
|
|
20542
20668
|
else {
|
|
@@ -21006,7 +21132,7 @@ class WalkerMarkdownService {
|
|
|
21006
21132
|
* @param backtest - Whether running in backtest mode
|
|
21007
21133
|
* @returns Unique string key for memoization
|
|
21008
21134
|
*/
|
|
21009
|
-
const CREATE_KEY_FN$
|
|
21135
|
+
const CREATE_KEY_FN$d = (exchangeName, frameName, backtest) => {
|
|
21010
21136
|
const parts = [exchangeName];
|
|
21011
21137
|
if (frameName)
|
|
21012
21138
|
parts.push(frameName);
|
|
@@ -21373,7 +21499,7 @@ class HeatMarkdownService {
|
|
|
21373
21499
|
* Memoized function to get or create HeatmapStorage for exchange, frame and backtest mode.
|
|
21374
21500
|
* Each exchangeName + frameName + backtest mode combination gets its own isolated heatmap storage instance.
|
|
21375
21501
|
*/
|
|
21376
|
-
this.getStorage = functoolsKit.memoize(([exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
21502
|
+
this.getStorage = functoolsKit.memoize(([exchangeName, frameName, backtest]) => CREATE_KEY_FN$d(exchangeName, frameName, backtest), (exchangeName, frameName, backtest) => new HeatmapStorage(exchangeName, frameName, backtest));
|
|
21377
21503
|
/**
|
|
21378
21504
|
* Subscribes to signal emitter to receive tick events.
|
|
21379
21505
|
* Protected against multiple subscriptions.
|
|
@@ -21568,7 +21694,7 @@ class HeatMarkdownService {
|
|
|
21568
21694
|
payload,
|
|
21569
21695
|
});
|
|
21570
21696
|
if (payload) {
|
|
21571
|
-
const key = CREATE_KEY_FN$
|
|
21697
|
+
const key = CREATE_KEY_FN$d(payload.exchangeName, payload.frameName, payload.backtest);
|
|
21572
21698
|
this.getStorage.clear(key);
|
|
21573
21699
|
}
|
|
21574
21700
|
else {
|
|
@@ -22599,7 +22725,7 @@ class ClientPartial {
|
|
|
22599
22725
|
* @param backtest - Whether running in backtest mode
|
|
22600
22726
|
* @returns Unique string key for memoization
|
|
22601
22727
|
*/
|
|
22602
|
-
const CREATE_KEY_FN$
|
|
22728
|
+
const CREATE_KEY_FN$c = (signalId, backtest) => `${signalId}:${backtest ? "backtest" : "live"}`;
|
|
22603
22729
|
/**
|
|
22604
22730
|
* Creates a callback function for emitting profit events to partialProfitSubject.
|
|
22605
22731
|
*
|
|
@@ -22721,7 +22847,7 @@ class PartialConnectionService {
|
|
|
22721
22847
|
* Key format: "signalId:backtest" or "signalId:live"
|
|
22722
22848
|
* Value: ClientPartial instance with logger and event emitters
|
|
22723
22849
|
*/
|
|
22724
|
-
this.getPartial = functoolsKit.memoize(([signalId, backtest]) => CREATE_KEY_FN$
|
|
22850
|
+
this.getPartial = functoolsKit.memoize(([signalId, backtest]) => CREATE_KEY_FN$c(signalId, backtest), (signalId, backtest) => {
|
|
22725
22851
|
return new ClientPartial({
|
|
22726
22852
|
signalId,
|
|
22727
22853
|
logger: this.loggerService,
|
|
@@ -22811,7 +22937,7 @@ class PartialConnectionService {
|
|
|
22811
22937
|
const partial = this.getPartial(data.id, backtest);
|
|
22812
22938
|
await partial.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
|
|
22813
22939
|
await partial.clear(symbol, data, priceClose, backtest);
|
|
22814
|
-
const key = CREATE_KEY_FN$
|
|
22940
|
+
const key = CREATE_KEY_FN$c(data.id, backtest);
|
|
22815
22941
|
this.getPartial.clear(key);
|
|
22816
22942
|
};
|
|
22817
22943
|
}
|
|
@@ -22827,7 +22953,7 @@ class PartialConnectionService {
|
|
|
22827
22953
|
* @param backtest - Whether running in backtest mode
|
|
22828
22954
|
* @returns Unique string key for memoization
|
|
22829
22955
|
*/
|
|
22830
|
-
const CREATE_KEY_FN$
|
|
22956
|
+
const CREATE_KEY_FN$b = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
22831
22957
|
const parts = [symbol, strategyName, exchangeName];
|
|
22832
22958
|
if (frameName)
|
|
22833
22959
|
parts.push(frameName);
|
|
@@ -23052,7 +23178,7 @@ class PartialMarkdownService {
|
|
|
23052
23178
|
* Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
23053
23179
|
* Each combination gets its own isolated storage instance.
|
|
23054
23180
|
*/
|
|
23055
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
23181
|
+
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$b(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName, backtest) => new ReportStorage$4(symbol, strategyName, exchangeName, frameName));
|
|
23056
23182
|
/**
|
|
23057
23183
|
* Subscribes to partial profit/loss signal emitters to receive events.
|
|
23058
23184
|
* Protected against multiple subscriptions.
|
|
@@ -23262,7 +23388,7 @@ class PartialMarkdownService {
|
|
|
23262
23388
|
payload,
|
|
23263
23389
|
});
|
|
23264
23390
|
if (payload) {
|
|
23265
|
-
const key = CREATE_KEY_FN$
|
|
23391
|
+
const key = CREATE_KEY_FN$b(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
23266
23392
|
this.getStorage.clear(key);
|
|
23267
23393
|
}
|
|
23268
23394
|
else {
|
|
@@ -23278,7 +23404,7 @@ class PartialMarkdownService {
|
|
|
23278
23404
|
* @param context - Context with strategyName, exchangeName, frameName
|
|
23279
23405
|
* @returns Unique string key for memoization
|
|
23280
23406
|
*/
|
|
23281
|
-
const CREATE_KEY_FN$
|
|
23407
|
+
const CREATE_KEY_FN$a = (context) => {
|
|
23282
23408
|
const parts = [context.strategyName, context.exchangeName];
|
|
23283
23409
|
if (context.frameName)
|
|
23284
23410
|
parts.push(context.frameName);
|
|
@@ -23352,7 +23478,7 @@ class PartialGlobalService {
|
|
|
23352
23478
|
* @param context - Context with strategyName, exchangeName and frameName
|
|
23353
23479
|
* @param methodName - Name of the calling method for error tracking
|
|
23354
23480
|
*/
|
|
23355
|
-
this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$
|
|
23481
|
+
this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$a(context), (context, methodName) => {
|
|
23356
23482
|
this.loggerService.log("partialGlobalService validate", {
|
|
23357
23483
|
context,
|
|
23358
23484
|
methodName,
|
|
@@ -23807,7 +23933,7 @@ class ClientBreakeven {
|
|
|
23807
23933
|
* @param backtest - Whether running in backtest mode
|
|
23808
23934
|
* @returns Unique string key for memoization
|
|
23809
23935
|
*/
|
|
23810
|
-
const CREATE_KEY_FN$
|
|
23936
|
+
const CREATE_KEY_FN$9 = (signalId, backtest) => `${signalId}:${backtest ? "backtest" : "live"}`;
|
|
23811
23937
|
/**
|
|
23812
23938
|
* Creates a callback function for emitting breakeven events to breakevenSubject.
|
|
23813
23939
|
*
|
|
@@ -23893,7 +24019,7 @@ class BreakevenConnectionService {
|
|
|
23893
24019
|
* Key format: "signalId:backtest" or "signalId:live"
|
|
23894
24020
|
* Value: ClientBreakeven instance with logger and event emitter
|
|
23895
24021
|
*/
|
|
23896
|
-
this.getBreakeven = functoolsKit.memoize(([signalId, backtest]) => CREATE_KEY_FN$
|
|
24022
|
+
this.getBreakeven = functoolsKit.memoize(([signalId, backtest]) => CREATE_KEY_FN$9(signalId, backtest), (signalId, backtest) => {
|
|
23897
24023
|
return new ClientBreakeven({
|
|
23898
24024
|
signalId,
|
|
23899
24025
|
logger: this.loggerService,
|
|
@@ -23954,7 +24080,7 @@ class BreakevenConnectionService {
|
|
|
23954
24080
|
const breakeven = this.getBreakeven(data.id, backtest);
|
|
23955
24081
|
await breakeven.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
|
|
23956
24082
|
await breakeven.clear(symbol, data, priceClose, backtest);
|
|
23957
|
-
const key = CREATE_KEY_FN$
|
|
24083
|
+
const key = CREATE_KEY_FN$9(data.id, backtest);
|
|
23958
24084
|
this.getBreakeven.clear(key);
|
|
23959
24085
|
};
|
|
23960
24086
|
}
|
|
@@ -23970,7 +24096,7 @@ class BreakevenConnectionService {
|
|
|
23970
24096
|
* @param backtest - Whether running in backtest mode
|
|
23971
24097
|
* @returns Unique string key for memoization
|
|
23972
24098
|
*/
|
|
23973
|
-
const CREATE_KEY_FN$
|
|
24099
|
+
const CREATE_KEY_FN$8 = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
23974
24100
|
const parts = [symbol, strategyName, exchangeName];
|
|
23975
24101
|
if (frameName)
|
|
23976
24102
|
parts.push(frameName);
|
|
@@ -24147,7 +24273,7 @@ class BreakevenMarkdownService {
|
|
|
24147
24273
|
* Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
24148
24274
|
* Each combination gets its own isolated storage instance.
|
|
24149
24275
|
*/
|
|
24150
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
24276
|
+
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$8(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName, backtest) => new ReportStorage$3(symbol, strategyName, exchangeName, frameName));
|
|
24151
24277
|
/**
|
|
24152
24278
|
* Subscribes to breakeven signal emitter to receive events.
|
|
24153
24279
|
* Protected against multiple subscriptions.
|
|
@@ -24336,7 +24462,7 @@ class BreakevenMarkdownService {
|
|
|
24336
24462
|
payload,
|
|
24337
24463
|
});
|
|
24338
24464
|
if (payload) {
|
|
24339
|
-
const key = CREATE_KEY_FN$
|
|
24465
|
+
const key = CREATE_KEY_FN$8(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
24340
24466
|
this.getStorage.clear(key);
|
|
24341
24467
|
}
|
|
24342
24468
|
else {
|
|
@@ -24352,7 +24478,7 @@ class BreakevenMarkdownService {
|
|
|
24352
24478
|
* @param context - Context with strategyName, exchangeName, frameName
|
|
24353
24479
|
* @returns Unique string key for memoization
|
|
24354
24480
|
*/
|
|
24355
|
-
const CREATE_KEY_FN$
|
|
24481
|
+
const CREATE_KEY_FN$7 = (context) => {
|
|
24356
24482
|
const parts = [context.strategyName, context.exchangeName];
|
|
24357
24483
|
if (context.frameName)
|
|
24358
24484
|
parts.push(context.frameName);
|
|
@@ -24426,7 +24552,7 @@ class BreakevenGlobalService {
|
|
|
24426
24552
|
* @param context - Context with strategyName, exchangeName and frameName
|
|
24427
24553
|
* @param methodName - Name of the calling method for error tracking
|
|
24428
24554
|
*/
|
|
24429
|
-
this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$
|
|
24555
|
+
this.validate = functoolsKit.memoize(([context]) => CREATE_KEY_FN$7(context), (context, methodName) => {
|
|
24430
24556
|
this.loggerService.log("breakevenGlobalService validate", {
|
|
24431
24557
|
context,
|
|
24432
24558
|
methodName,
|
|
@@ -24646,7 +24772,7 @@ class ConfigValidationService {
|
|
|
24646
24772
|
* @param backtest - Whether running in backtest mode
|
|
24647
24773
|
* @returns Unique string key for memoization
|
|
24648
24774
|
*/
|
|
24649
|
-
const CREATE_KEY_FN$
|
|
24775
|
+
const CREATE_KEY_FN$6 = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
24650
24776
|
const parts = [symbol, strategyName, exchangeName];
|
|
24651
24777
|
if (frameName)
|
|
24652
24778
|
parts.push(frameName);
|
|
@@ -24815,7 +24941,7 @@ class RiskMarkdownService {
|
|
|
24815
24941
|
* Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
24816
24942
|
* Each combination gets its own isolated storage instance.
|
|
24817
24943
|
*/
|
|
24818
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
24944
|
+
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$6(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName, backtest) => new ReportStorage$2(symbol, strategyName, exchangeName, frameName));
|
|
24819
24945
|
/**
|
|
24820
24946
|
* Subscribes to risk rejection emitter to receive rejection events.
|
|
24821
24947
|
* Protected against multiple subscriptions.
|
|
@@ -25004,7 +25130,7 @@ class RiskMarkdownService {
|
|
|
25004
25130
|
payload,
|
|
25005
25131
|
});
|
|
25006
25132
|
if (payload) {
|
|
25007
|
-
const key = CREATE_KEY_FN$
|
|
25133
|
+
const key = CREATE_KEY_FN$6(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
25008
25134
|
this.getStorage.clear(key);
|
|
25009
25135
|
}
|
|
25010
25136
|
else {
|
|
@@ -27692,7 +27818,7 @@ class SyncReportService {
|
|
|
27692
27818
|
* @returns Colon-separated key string for memoization
|
|
27693
27819
|
* @internal
|
|
27694
27820
|
*/
|
|
27695
|
-
const CREATE_KEY_FN$
|
|
27821
|
+
const CREATE_KEY_FN$5 = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
27696
27822
|
const parts = [symbol, strategyName, exchangeName];
|
|
27697
27823
|
if (frameName)
|
|
27698
27824
|
parts.push(frameName);
|
|
@@ -27940,7 +28066,7 @@ class StrategyMarkdownService {
|
|
|
27940
28066
|
*
|
|
27941
28067
|
* @internal
|
|
27942
28068
|
*/
|
|
27943
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
28069
|
+
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$5(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName) => new ReportStorage$1(symbol, strategyName, exchangeName, frameName));
|
|
27944
28070
|
/**
|
|
27945
28071
|
* Records a cancel-scheduled event when a scheduled signal is cancelled.
|
|
27946
28072
|
*
|
|
@@ -28508,7 +28634,7 @@ class StrategyMarkdownService {
|
|
|
28508
28634
|
this.clear = async (payload) => {
|
|
28509
28635
|
this.loggerService.log("strategyMarkdownService clear", { payload });
|
|
28510
28636
|
if (payload) {
|
|
28511
|
-
const key = CREATE_KEY_FN$
|
|
28637
|
+
const key = CREATE_KEY_FN$5(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
28512
28638
|
this.getStorage.clear(key);
|
|
28513
28639
|
}
|
|
28514
28640
|
else {
|
|
@@ -28616,7 +28742,7 @@ class StrategyMarkdownService {
|
|
|
28616
28742
|
* Creates a unique key for memoizing ReportStorage instances.
|
|
28617
28743
|
* Key format: "symbol:strategyName:exchangeName[:frameName]:backtest|live"
|
|
28618
28744
|
*/
|
|
28619
|
-
const CREATE_KEY_FN$
|
|
28745
|
+
const CREATE_KEY_FN$4 = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
28620
28746
|
const parts = [symbol, strategyName, exchangeName];
|
|
28621
28747
|
if (frameName)
|
|
28622
28748
|
parts.push(frameName);
|
|
@@ -28748,7 +28874,7 @@ class ReportStorage {
|
|
|
28748
28874
|
class SyncMarkdownService {
|
|
28749
28875
|
constructor() {
|
|
28750
28876
|
this.loggerService = inject(TYPES.loggerService);
|
|
28751
|
-
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
28877
|
+
this.getStorage = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$4(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName, backtest) => new ReportStorage(symbol, strategyName, exchangeName, frameName));
|
|
28752
28878
|
this.subscribe = functoolsKit.singleshot(() => {
|
|
28753
28879
|
this.loggerService.log("syncMarkdownService init");
|
|
28754
28880
|
const unsubscribe = syncSubject.subscribe(this.tick);
|
|
@@ -28823,7 +28949,7 @@ class SyncMarkdownService {
|
|
|
28823
28949
|
this.clear = async (payload) => {
|
|
28824
28950
|
this.loggerService.log("syncMarkdownService clear", { payload });
|
|
28825
28951
|
if (payload) {
|
|
28826
|
-
const key = CREATE_KEY_FN$
|
|
28952
|
+
const key = CREATE_KEY_FN$4(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
28827
28953
|
this.getStorage.clear(key);
|
|
28828
28954
|
}
|
|
28829
28955
|
else {
|
|
@@ -28833,6 +28959,275 @@ class SyncMarkdownService {
|
|
|
28833
28959
|
}
|
|
28834
28960
|
}
|
|
28835
28961
|
|
|
28962
|
+
const LISTEN_TIMEOUT$1 = 120000;
|
|
28963
|
+
/**
|
|
28964
|
+
* Creates a unique memoization key for a price stream.
|
|
28965
|
+
* Key format: "symbol:strategyName:exchangeName[:frameName]:backtest|live"
|
|
28966
|
+
*
|
|
28967
|
+
* @param symbol - Trading pair symbol (e.g., "BTCUSDT")
|
|
28968
|
+
* @param strategyName - Strategy identifier
|
|
28969
|
+
* @param exchangeName - Exchange identifier
|
|
28970
|
+
* @param frameName - Frame identifier (omitted when empty)
|
|
28971
|
+
* @param backtest - Whether running in backtest mode
|
|
28972
|
+
* @returns Unique string key for memoization
|
|
28973
|
+
*/
|
|
28974
|
+
const CREATE_KEY_FN$3 = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
28975
|
+
const parts = [symbol, strategyName, exchangeName];
|
|
28976
|
+
if (frameName)
|
|
28977
|
+
parts.push(frameName);
|
|
28978
|
+
parts.push(backtest ? "backtest" : "live");
|
|
28979
|
+
return parts.join(":");
|
|
28980
|
+
};
|
|
28981
|
+
/**
|
|
28982
|
+
* Service for tracking the latest market price per symbol-strategy-exchange-frame combination.
|
|
28983
|
+
*
|
|
28984
|
+
* Maintains a memoized BehaviorSubject per unique key that is updated on every strategy tick
|
|
28985
|
+
* by StrategyConnectionService. Consumers can synchronously read the last known price or
|
|
28986
|
+
* await the first value if none has arrived yet.
|
|
28987
|
+
*
|
|
28988
|
+
* Primary use case: providing the current price outside of a tick execution context,
|
|
28989
|
+
* e.g., when a command is triggered between ticks.
|
|
28990
|
+
*
|
|
28991
|
+
* Features:
|
|
28992
|
+
* - One BehaviorSubject per (symbol, strategyName, exchangeName, frameName, backtest) key
|
|
28993
|
+
* - Falls back to ExchangeConnectionService.getAveragePrice when called inside an execution context
|
|
28994
|
+
* - Waits up to LISTEN_TIMEOUT ms for the first price if none is cached yet
|
|
28995
|
+
* - clear() disposes the BehaviorSubject for a single key or all keys
|
|
28996
|
+
*
|
|
28997
|
+
* Architecture:
|
|
28998
|
+
* - Registered as singleton in DI container
|
|
28999
|
+
* - Updated by StrategyConnectionService after each tick
|
|
29000
|
+
* - Cleared by Backtest/Live/Walker at strategy start to prevent stale data
|
|
29001
|
+
*
|
|
29002
|
+
* @example
|
|
29003
|
+
* ```typescript
|
|
29004
|
+
* const price = await backtest.priceMetaService.getCurrentPrice("BTCUSDT", context, false);
|
|
29005
|
+
* ```
|
|
29006
|
+
*/
|
|
29007
|
+
class PriceMetaService {
|
|
29008
|
+
constructor() {
|
|
29009
|
+
this.loggerService = inject(TYPES.loggerService);
|
|
29010
|
+
this.exchangeConnectionService = inject(TYPES.exchangeConnectionService);
|
|
29011
|
+
/**
|
|
29012
|
+
* Memoized factory for BehaviorSubject streams keyed by (symbol, strategyName, exchangeName, frameName, backtest).
|
|
29013
|
+
*
|
|
29014
|
+
* Each subject holds the latest currentPrice emitted by the strategy iterator for that key.
|
|
29015
|
+
* Instances are cached until clear() is called.
|
|
29016
|
+
*/
|
|
29017
|
+
this.getSource = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$3(symbol, strategyName, exchangeName, frameName, backtest), () => new functoolsKit.BehaviorSubject());
|
|
29018
|
+
/**
|
|
29019
|
+
* Returns the current market price for the given symbol and context.
|
|
29020
|
+
*
|
|
29021
|
+
* When called inside an execution context (i.e., during a signal handler or action),
|
|
29022
|
+
* delegates to ExchangeConnectionService.getAveragePrice for the live exchange price.
|
|
29023
|
+
* Otherwise, reads the last value from the cached BehaviorSubject. If no value has
|
|
29024
|
+
* been emitted yet, waits up to LISTEN_TIMEOUT ms for the first tick before throwing.
|
|
29025
|
+
*
|
|
29026
|
+
* @param symbol - Trading pair symbol (e.g., "BTCUSDT")
|
|
29027
|
+
* @param context - Strategy, exchange, and frame identifiers
|
|
29028
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
29029
|
+
* @returns Current market price in quote currency
|
|
29030
|
+
* @throws When no price arrives within LISTEN_TIMEOUT ms
|
|
29031
|
+
*/
|
|
29032
|
+
this.getCurrentPrice = async (symbol, context, backtest) => {
|
|
29033
|
+
this.loggerService.log("priceMetaService getCurrentPrice", {
|
|
29034
|
+
symbol,
|
|
29035
|
+
context,
|
|
29036
|
+
backtest,
|
|
29037
|
+
});
|
|
29038
|
+
if (ExecutionContextService.hasContext() &&
|
|
29039
|
+
MethodContextService.hasContext()) {
|
|
29040
|
+
return await this.exchangeConnectionService.getAveragePrice(symbol);
|
|
29041
|
+
}
|
|
29042
|
+
const source = this.getSource(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
29043
|
+
if (source.data) {
|
|
29044
|
+
return source.data;
|
|
29045
|
+
}
|
|
29046
|
+
console.warn(`PriceMetaService: No currentPrice available for ${CREATE_KEY_FN$3(symbol, context.strategyName, context.exchangeName, context.frameName, backtest)}. Trying to fetch from strategy iterator as a fallback...`);
|
|
29047
|
+
const currentPrice = await functoolsKit.waitForNext(source, (data) => !!data, LISTEN_TIMEOUT$1);
|
|
29048
|
+
if (typeof currentPrice === "symbol") {
|
|
29049
|
+
throw new Error(`PriceMetaService: Timeout while waiting for currentPrice for ${CREATE_KEY_FN$3(symbol, context.strategyName, context.exchangeName, context.frameName, backtest)}`);
|
|
29050
|
+
}
|
|
29051
|
+
return currentPrice;
|
|
29052
|
+
};
|
|
29053
|
+
/**
|
|
29054
|
+
* Pushes a new price value into the BehaviorSubject for the given key.
|
|
29055
|
+
*
|
|
29056
|
+
* Called by StrategyConnectionService after each strategy tick to keep
|
|
29057
|
+
* the cached price up to date.
|
|
29058
|
+
*
|
|
29059
|
+
* @param symbol - Trading pair symbol (e.g., "BTCUSDT")
|
|
29060
|
+
* @param currentPrice - The latest price from the tick
|
|
29061
|
+
* @param context - Strategy, exchange, and frame identifiers
|
|
29062
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
29063
|
+
*/
|
|
29064
|
+
this.next = async (symbol, currentPrice, context, backtest) => {
|
|
29065
|
+
this.loggerService.log("priceMetaService next", {
|
|
29066
|
+
symbol,
|
|
29067
|
+
currentPrice,
|
|
29068
|
+
context,
|
|
29069
|
+
backtest,
|
|
29070
|
+
});
|
|
29071
|
+
const source = this.getSource(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
29072
|
+
source.next(currentPrice);
|
|
29073
|
+
};
|
|
29074
|
+
/**
|
|
29075
|
+
* Disposes cached BehaviorSubject(s) to free memory and prevent stale data.
|
|
29076
|
+
*
|
|
29077
|
+
* When called without arguments, clears all memoized price streams.
|
|
29078
|
+
* When called with a payload, clears only the stream for the specified key.
|
|
29079
|
+
* Should be called at strategy start (Backtest/Live/Walker) to reset state.
|
|
29080
|
+
*
|
|
29081
|
+
* @param payload - Optional key to clear a single stream; omit to clear all
|
|
29082
|
+
*/
|
|
29083
|
+
this.clear = (payload) => {
|
|
29084
|
+
this.loggerService.log("priceMetaService clear", {
|
|
29085
|
+
payload
|
|
29086
|
+
});
|
|
29087
|
+
if (!payload) {
|
|
29088
|
+
this.getSource.clear();
|
|
29089
|
+
return;
|
|
29090
|
+
}
|
|
29091
|
+
const key = CREATE_KEY_FN$3(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
29092
|
+
this.getSource.clear(key);
|
|
29093
|
+
};
|
|
29094
|
+
}
|
|
29095
|
+
}
|
|
29096
|
+
|
|
29097
|
+
const LISTEN_TIMEOUT = 120000;
|
|
29098
|
+
/**
|
|
29099
|
+
* Creates a unique memoization key for a timestamp stream.
|
|
29100
|
+
* Key format: "symbol:strategyName:exchangeName[:frameName]:backtest|live"
|
|
29101
|
+
*
|
|
29102
|
+
* @param symbol - Trading pair symbol (e.g., "BTCUSDT")
|
|
29103
|
+
* @param strategyName - Strategy identifier
|
|
29104
|
+
* @param exchangeName - Exchange identifier
|
|
29105
|
+
* @param frameName - Frame identifier (omitted when empty)
|
|
29106
|
+
* @param backtest - Whether running in backtest mode
|
|
29107
|
+
* @returns Unique string key for memoization
|
|
29108
|
+
*/
|
|
29109
|
+
const CREATE_KEY_FN$2 = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
29110
|
+
const parts = [symbol, strategyName, exchangeName];
|
|
29111
|
+
if (frameName)
|
|
29112
|
+
parts.push(frameName);
|
|
29113
|
+
parts.push(backtest ? "backtest" : "live");
|
|
29114
|
+
return parts.join(":");
|
|
29115
|
+
};
|
|
29116
|
+
/**
|
|
29117
|
+
* Service for tracking the latest candle timestamp per symbol-strategy-exchange-frame combination.
|
|
29118
|
+
*
|
|
29119
|
+
* Maintains a memoized BehaviorSubject per unique key that is updated on every strategy tick
|
|
29120
|
+
* by StrategyConnectionService. Consumers can synchronously read the last known timestamp or
|
|
29121
|
+
* await the first value if none has arrived yet.
|
|
29122
|
+
*
|
|
29123
|
+
* Primary use case: providing the current candle time outside of a tick execution context,
|
|
29124
|
+
* e.g., when a command is triggered between ticks.
|
|
29125
|
+
*
|
|
29126
|
+
* Features:
|
|
29127
|
+
* - One BehaviorSubject per (symbol, strategyName, exchangeName, frameName, backtest) key
|
|
29128
|
+
* - Falls back to ExecutionContextService.context.when when called inside an execution context
|
|
29129
|
+
* - Waits up to LISTEN_TIMEOUT ms for the first timestamp if none is cached yet
|
|
29130
|
+
* - clear() disposes the BehaviorSubject for a single key or all keys
|
|
29131
|
+
*
|
|
29132
|
+
* Architecture:
|
|
29133
|
+
* - Registered as singleton in DI container
|
|
29134
|
+
* - Updated by StrategyConnectionService after each tick
|
|
29135
|
+
* - Cleared by Backtest/Live/Walker at strategy start to prevent stale data
|
|
29136
|
+
*
|
|
29137
|
+
* @example
|
|
29138
|
+
* ```typescript
|
|
29139
|
+
* const ts = await backtest.timeMetaService.getTimestamp("BTCUSDT", context, false);
|
|
29140
|
+
* ```
|
|
29141
|
+
*/
|
|
29142
|
+
class TimeMetaService {
|
|
29143
|
+
constructor() {
|
|
29144
|
+
this.loggerService = inject(TYPES.loggerService);
|
|
29145
|
+
this.executionContextService = inject(TYPES.executionContextService);
|
|
29146
|
+
/**
|
|
29147
|
+
* Memoized factory for BehaviorSubject streams keyed by (symbol, strategyName, exchangeName, frameName, backtest).
|
|
29148
|
+
*
|
|
29149
|
+
* Each subject holds the latest createdAt timestamp emitted by the strategy iterator for that key.
|
|
29150
|
+
* Instances are cached until clear() is called.
|
|
29151
|
+
*/
|
|
29152
|
+
this.getSource = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$2(symbol, strategyName, exchangeName, frameName, backtest), () => new functoolsKit.BehaviorSubject());
|
|
29153
|
+
/**
|
|
29154
|
+
* Returns the current candle timestamp (in milliseconds) for the given symbol and context.
|
|
29155
|
+
*
|
|
29156
|
+
* When called inside an execution context (i.e., during a signal handler or action),
|
|
29157
|
+
* reads the timestamp directly from ExecutionContextService.context.when.
|
|
29158
|
+
* Otherwise, reads the last value from the cached BehaviorSubject. If no value has
|
|
29159
|
+
* been emitted yet, waits up to LISTEN_TIMEOUT ms for the first tick before throwing.
|
|
29160
|
+
*
|
|
29161
|
+
* @param symbol - Trading pair symbol (e.g., "BTCUSDT")
|
|
29162
|
+
* @param context - Strategy, exchange, and frame identifiers
|
|
29163
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
29164
|
+
* @returns Unix timestamp in milliseconds of the latest processed candle
|
|
29165
|
+
* @throws When no timestamp arrives within LISTEN_TIMEOUT ms
|
|
29166
|
+
*/
|
|
29167
|
+
this.getTimestamp = async (symbol, context, backtest) => {
|
|
29168
|
+
this.loggerService.log("timeMetaService getTimestamp", {
|
|
29169
|
+
symbol,
|
|
29170
|
+
context,
|
|
29171
|
+
backtest,
|
|
29172
|
+
});
|
|
29173
|
+
if (ExecutionContextService.hasContext()) {
|
|
29174
|
+
return this.executionContextService.context.when.getTime();
|
|
29175
|
+
}
|
|
29176
|
+
const source = this.getSource(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
29177
|
+
if (source.data) {
|
|
29178
|
+
return source.data;
|
|
29179
|
+
}
|
|
29180
|
+
console.warn(`TimeMetaService: No timestamp available for ${CREATE_KEY_FN$2(symbol, context.strategyName, context.exchangeName, context.frameName, backtest)}. Trying to fetch from strategy iterator as a fallback...`);
|
|
29181
|
+
const timestamp = await functoolsKit.waitForNext(source, (data) => !!data, LISTEN_TIMEOUT);
|
|
29182
|
+
if (typeof timestamp === "symbol") {
|
|
29183
|
+
throw new Error(`TimeMetaService: Timeout while waiting for timestamp for ${CREATE_KEY_FN$2(symbol, context.strategyName, context.exchangeName, context.frameName, backtest)}`);
|
|
29184
|
+
}
|
|
29185
|
+
return timestamp;
|
|
29186
|
+
};
|
|
29187
|
+
/**
|
|
29188
|
+
* Pushes a new timestamp value into the BehaviorSubject for the given key.
|
|
29189
|
+
*
|
|
29190
|
+
* Called by StrategyConnectionService after each strategy tick to keep
|
|
29191
|
+
* the cached timestamp up to date.
|
|
29192
|
+
*
|
|
29193
|
+
* @param symbol - Trading pair symbol (e.g., "BTCUSDT")
|
|
29194
|
+
* @param timestamp - The createdAt timestamp from the tick (milliseconds)
|
|
29195
|
+
* @param context - Strategy, exchange, and frame identifiers
|
|
29196
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
29197
|
+
*/
|
|
29198
|
+
this.next = async (symbol, timestamp, context, backtest) => {
|
|
29199
|
+
this.loggerService.log("timeMetaService next", {
|
|
29200
|
+
symbol,
|
|
29201
|
+
timestamp,
|
|
29202
|
+
context,
|
|
29203
|
+
backtest,
|
|
29204
|
+
});
|
|
29205
|
+
const source = this.getSource(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
29206
|
+
source.next(timestamp);
|
|
29207
|
+
};
|
|
29208
|
+
/**
|
|
29209
|
+
* Disposes cached BehaviorSubject(s) to free memory and prevent stale data.
|
|
29210
|
+
*
|
|
29211
|
+
* When called without arguments, clears all memoized timestamp streams.
|
|
29212
|
+
* When called with a payload, clears only the stream for the specified key.
|
|
29213
|
+
* Should be called at strategy start (Backtest/Live/Walker) to reset state.
|
|
29214
|
+
*
|
|
29215
|
+
* @param payload - Optional key to clear a single stream; omit to clear all
|
|
29216
|
+
*/
|
|
29217
|
+
this.clear = (payload) => {
|
|
29218
|
+
this.loggerService.log("timeMetaService clear", {
|
|
29219
|
+
payload,
|
|
29220
|
+
});
|
|
29221
|
+
if (!payload) {
|
|
29222
|
+
this.getSource.clear();
|
|
29223
|
+
return;
|
|
29224
|
+
}
|
|
29225
|
+
const key = CREATE_KEY_FN$2(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
29226
|
+
this.getSource.clear(key);
|
|
29227
|
+
};
|
|
29228
|
+
}
|
|
29229
|
+
}
|
|
29230
|
+
|
|
28836
29231
|
{
|
|
28837
29232
|
provide(TYPES.loggerService, () => new LoggerService());
|
|
28838
29233
|
}
|
|
@@ -28865,6 +29260,10 @@ class SyncMarkdownService {
|
|
|
28865
29260
|
provide(TYPES.actionCoreService, () => new ActionCoreService());
|
|
28866
29261
|
provide(TYPES.frameCoreService, () => new FrameCoreService());
|
|
28867
29262
|
}
|
|
29263
|
+
{
|
|
29264
|
+
provide(TYPES.priceMetaService, () => new PriceMetaService());
|
|
29265
|
+
provide(TYPES.timeMetaService, () => new TimeMetaService());
|
|
29266
|
+
}
|
|
28868
29267
|
{
|
|
28869
29268
|
provide(TYPES.sizingGlobalService, () => new SizingGlobalService());
|
|
28870
29269
|
provide(TYPES.riskGlobalService, () => new RiskGlobalService());
|
|
@@ -28956,6 +29355,10 @@ const coreServices = {
|
|
|
28956
29355
|
actionCoreService: inject(TYPES.actionCoreService),
|
|
28957
29356
|
frameCoreService: inject(TYPES.frameCoreService),
|
|
28958
29357
|
};
|
|
29358
|
+
const metaServices = {
|
|
29359
|
+
timeMetaService: inject(TYPES.timeMetaService),
|
|
29360
|
+
priceMetaService: inject(TYPES.priceMetaService),
|
|
29361
|
+
};
|
|
28959
29362
|
const globalServices = {
|
|
28960
29363
|
sizingGlobalService: inject(TYPES.sizingGlobalService),
|
|
28961
29364
|
riskGlobalService: inject(TYPES.riskGlobalService),
|
|
@@ -29020,6 +29423,7 @@ const backtest = {
|
|
|
29020
29423
|
...connectionServices,
|
|
29021
29424
|
...schemaServices,
|
|
29022
29425
|
...coreServices,
|
|
29426
|
+
...metaServices,
|
|
29023
29427
|
...globalServices,
|
|
29024
29428
|
...commandServices,
|
|
29025
29429
|
...logicPrivateServices,
|
|
@@ -34506,6 +34910,20 @@ class BacktestInstance {
|
|
|
34506
34910
|
frameName: context.frameName,
|
|
34507
34911
|
backtest: true,
|
|
34508
34912
|
});
|
|
34913
|
+
bt.timeMetaService.clear({
|
|
34914
|
+
symbol,
|
|
34915
|
+
strategyName: context.strategyName,
|
|
34916
|
+
exchangeName: context.exchangeName,
|
|
34917
|
+
frameName: context.frameName,
|
|
34918
|
+
backtest: true,
|
|
34919
|
+
});
|
|
34920
|
+
bt.priceMetaService.clear({
|
|
34921
|
+
symbol,
|
|
34922
|
+
strategyName: context.strategyName,
|
|
34923
|
+
exchangeName: context.exchangeName,
|
|
34924
|
+
frameName: context.frameName,
|
|
34925
|
+
backtest: true,
|
|
34926
|
+
});
|
|
34509
34927
|
}
|
|
34510
34928
|
{
|
|
34511
34929
|
const { riskName, riskList, actions } = bt.strategySchemaService.get(context.strategyName);
|
|
@@ -36410,6 +36828,20 @@ class LiveInstance {
|
|
|
36410
36828
|
frameName: "",
|
|
36411
36829
|
backtest: false,
|
|
36412
36830
|
});
|
|
36831
|
+
bt.timeMetaService.clear({
|
|
36832
|
+
symbol,
|
|
36833
|
+
strategyName: context.strategyName,
|
|
36834
|
+
exchangeName: context.exchangeName,
|
|
36835
|
+
frameName: "",
|
|
36836
|
+
backtest: false,
|
|
36837
|
+
});
|
|
36838
|
+
bt.priceMetaService.clear({
|
|
36839
|
+
symbol,
|
|
36840
|
+
strategyName: context.strategyName,
|
|
36841
|
+
exchangeName: context.exchangeName,
|
|
36842
|
+
frameName: "",
|
|
36843
|
+
backtest: false,
|
|
36844
|
+
});
|
|
36413
36845
|
}
|
|
36414
36846
|
{
|
|
36415
36847
|
const { riskName, riskList, actions } = bt.strategySchemaService.get(context.strategyName);
|
|
@@ -40558,6 +40990,20 @@ class WalkerInstance {
|
|
|
40558
40990
|
frameName: walkerSchema.frameName,
|
|
40559
40991
|
backtest: true,
|
|
40560
40992
|
});
|
|
40993
|
+
bt.timeMetaService.clear({
|
|
40994
|
+
symbol,
|
|
40995
|
+
strategyName,
|
|
40996
|
+
exchangeName: walkerSchema.exchangeName,
|
|
40997
|
+
frameName: walkerSchema.frameName,
|
|
40998
|
+
backtest: true,
|
|
40999
|
+
});
|
|
41000
|
+
bt.priceMetaService.clear({
|
|
41001
|
+
symbol,
|
|
41002
|
+
strategyName,
|
|
41003
|
+
exchangeName: walkerSchema.exchangeName,
|
|
41004
|
+
frameName: walkerSchema.frameName,
|
|
41005
|
+
backtest: true,
|
|
41006
|
+
});
|
|
40561
41007
|
}
|
|
40562
41008
|
{
|
|
40563
41009
|
const { riskName, riskList, actions } = bt.strategySchemaService.get(strategyName);
|
|
@@ -43525,13 +43971,15 @@ class NotificationMemoryBacktestUtils {
|
|
|
43525
43971
|
* Handles signal sync events (signal-open, signal-close).
|
|
43526
43972
|
* @param data - The signal sync contract data
|
|
43527
43973
|
*/
|
|
43528
|
-
this.handleSync = async (data) => {
|
|
43974
|
+
this.handleSync = functoolsKit.trycatch(async (data) => {
|
|
43529
43975
|
bt.loggerService.info(NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_SYNC, {
|
|
43530
43976
|
signalId: data.signalId,
|
|
43531
43977
|
action: data.action,
|
|
43532
43978
|
});
|
|
43533
43979
|
this._addNotification(CREATE_SIGNAL_SYNC_NOTIFICATION_FN(data));
|
|
43534
|
-
}
|
|
43980
|
+
}, {
|
|
43981
|
+
defaultValue: null,
|
|
43982
|
+
});
|
|
43535
43983
|
/**
|
|
43536
43984
|
* Handles risk rejection event.
|
|
43537
43985
|
* @param data - The risk contract data
|
|
@@ -43640,8 +44088,10 @@ class NotificationDummyBacktestUtils {
|
|
|
43640
44088
|
/**
|
|
43641
44089
|
* No-op handler for signal sync event.
|
|
43642
44090
|
*/
|
|
43643
|
-
this.handleSync = async () => {
|
|
43644
|
-
}
|
|
44091
|
+
this.handleSync = functoolsKit.trycatch(async () => {
|
|
44092
|
+
}, {
|
|
44093
|
+
defaultValue: null,
|
|
44094
|
+
});
|
|
43645
44095
|
/**
|
|
43646
44096
|
* No-op handler for risk rejection event.
|
|
43647
44097
|
*/
|
|
@@ -43780,7 +44230,7 @@ class NotificationPersistBacktestUtils {
|
|
|
43780
44230
|
* Handles signal sync events (signal-open, signal-close).
|
|
43781
44231
|
* @param data - The signal sync contract data
|
|
43782
44232
|
*/
|
|
43783
|
-
this.handleSync = async (data) => {
|
|
44233
|
+
this.handleSync = functoolsKit.trycatch(async (data) => {
|
|
43784
44234
|
bt.loggerService.info(NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_HANDLE_SYNC, {
|
|
43785
44235
|
signalId: data.signalId,
|
|
43786
44236
|
action: data.action,
|
|
@@ -43788,7 +44238,9 @@ class NotificationPersistBacktestUtils {
|
|
|
43788
44238
|
await this.waitForInit();
|
|
43789
44239
|
this._addNotification(CREATE_SIGNAL_SYNC_NOTIFICATION_FN(data));
|
|
43790
44240
|
await this._updateNotifications();
|
|
43791
|
-
}
|
|
44241
|
+
}, {
|
|
44242
|
+
defaultValue: null,
|
|
44243
|
+
});
|
|
43792
44244
|
/**
|
|
43793
44245
|
* Handles risk rejection event.
|
|
43794
44246
|
* @param data - The risk contract data
|
|
@@ -43971,13 +44423,15 @@ class NotificationMemoryLiveUtils {
|
|
|
43971
44423
|
* Handles signal sync events (signal-open, signal-close).
|
|
43972
44424
|
* @param data - The signal sync contract data
|
|
43973
44425
|
*/
|
|
43974
|
-
this.handleSync = async (data) => {
|
|
44426
|
+
this.handleSync = functoolsKit.trycatch(async (data) => {
|
|
43975
44427
|
bt.loggerService.info(NOTIFICATION_MEMORY_LIVE_METHOD_NAME_HANDLE_SYNC, {
|
|
43976
44428
|
signalId: data.signalId,
|
|
43977
44429
|
action: data.action,
|
|
43978
44430
|
});
|
|
43979
44431
|
this._addNotification(CREATE_SIGNAL_SYNC_NOTIFICATION_FN(data));
|
|
43980
|
-
}
|
|
44432
|
+
}, {
|
|
44433
|
+
defaultValue: null,
|
|
44434
|
+
});
|
|
43981
44435
|
/**
|
|
43982
44436
|
* Handles risk rejection event.
|
|
43983
44437
|
* @param data - The risk contract data
|
|
@@ -44086,8 +44540,10 @@ class NotificationDummyLiveUtils {
|
|
|
44086
44540
|
/**
|
|
44087
44541
|
* No-op handler for signal sync event.
|
|
44088
44542
|
*/
|
|
44089
|
-
this.handleSync = async () => {
|
|
44090
|
-
}
|
|
44543
|
+
this.handleSync = functoolsKit.trycatch(async () => {
|
|
44544
|
+
}, {
|
|
44545
|
+
defaultValue: null,
|
|
44546
|
+
});
|
|
44091
44547
|
/**
|
|
44092
44548
|
* No-op handler for risk rejection event.
|
|
44093
44549
|
*/
|
|
@@ -44227,7 +44683,7 @@ class NotificationPersistLiveUtils {
|
|
|
44227
44683
|
* Handles signal sync events (signal-open, signal-close).
|
|
44228
44684
|
* @param data - The signal sync contract data
|
|
44229
44685
|
*/
|
|
44230
|
-
this.handleSync = async (data) => {
|
|
44686
|
+
this.handleSync = functoolsKit.trycatch(async (data) => {
|
|
44231
44687
|
bt.loggerService.info(NOTIFICATION_PERSIST_LIVE_METHOD_NAME_HANDLE_SYNC, {
|
|
44232
44688
|
signalId: data.signalId,
|
|
44233
44689
|
action: data.action,
|
|
@@ -44235,7 +44691,9 @@ class NotificationPersistLiveUtils {
|
|
|
44235
44691
|
await this.waitForInit();
|
|
44236
44692
|
this._addNotification(CREATE_SIGNAL_SYNC_NOTIFICATION_FN(data));
|
|
44237
44693
|
await this._updateNotifications();
|
|
44238
|
-
}
|
|
44694
|
+
}, {
|
|
44695
|
+
defaultValue: null,
|
|
44696
|
+
});
|
|
44239
44697
|
/**
|
|
44240
44698
|
* Handles risk rejection event.
|
|
44241
44699
|
* @param data - The risk contract data
|
|
@@ -44397,9 +44855,11 @@ class NotificationBacktestAdapter {
|
|
|
44397
44855
|
* Proxies call to the underlying notification adapter.
|
|
44398
44856
|
* @param data - The signal sync contract data
|
|
44399
44857
|
*/
|
|
44400
|
-
this.handleSync = async (data) => {
|
|
44858
|
+
this.handleSync = functoolsKit.trycatch(async (data) => {
|
|
44401
44859
|
return await this._notificationBacktestUtils.handleSync(data);
|
|
44402
|
-
}
|
|
44860
|
+
}, {
|
|
44861
|
+
defaultValue: null,
|
|
44862
|
+
});
|
|
44403
44863
|
/**
|
|
44404
44864
|
* Handles risk rejection event.
|
|
44405
44865
|
* Proxies call to the underlying notification adapter.
|
|
@@ -44541,9 +45001,11 @@ class NotificationLiveAdapter {
|
|
|
44541
45001
|
* Proxies call to the underlying notification adapter.
|
|
44542
45002
|
* @param data - The signal sync contract data
|
|
44543
45003
|
*/
|
|
44544
|
-
this.handleSync = async (data) => {
|
|
45004
|
+
this.handleSync = functoolsKit.trycatch(async (data) => {
|
|
44545
45005
|
return await this._notificationLiveUtils.handleSync(data);
|
|
44546
|
-
}
|
|
45006
|
+
}, {
|
|
45007
|
+
defaultValue: null,
|
|
45008
|
+
});
|
|
44547
45009
|
/**
|
|
44548
45010
|
* Handles risk rejection event.
|
|
44549
45011
|
* Proxies call to the underlying notification adapter.
|