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.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createActivator } from 'di-kit';
|
|
2
2
|
import { scoped } from 'di-scoped';
|
|
3
|
-
import { Subject, makeExtendable, singleshot, getErrorMessage, memoize, not, errorData, trycatch, retry, queued, sleep, randomString, str, isObject, ToolRegistry, typo, and, Source, resolveDocuments, timeout, TIMEOUT_SYMBOL as TIMEOUT_SYMBOL$1, compose, singlerun } from 'functools-kit';
|
|
3
|
+
import { Subject, makeExtendable, singleshot, getErrorMessage, memoize, not, errorData, trycatch, retry, queued, sleep, randomString, str, isObject, ToolRegistry, typo, and, Source, resolveDocuments, timeout, TIMEOUT_SYMBOL as TIMEOUT_SYMBOL$1, compose, BehaviorSubject, waitForNext, singlerun } from 'functools-kit';
|
|
4
4
|
import * as fs from 'fs/promises';
|
|
5
5
|
import fs__default, { stat, opendir, readFile } from 'fs/promises';
|
|
6
6
|
import path, { join, dirname } from 'path';
|
|
@@ -69,6 +69,10 @@ const coreServices$1 = {
|
|
|
69
69
|
actionCoreService: Symbol('actionCoreService'),
|
|
70
70
|
frameCoreService: Symbol('frameCoreService'),
|
|
71
71
|
};
|
|
72
|
+
const metaServices$1 = {
|
|
73
|
+
priceMetaService: Symbol('priceMetaService'),
|
|
74
|
+
timeMetaService: Symbol('timeMetaService'),
|
|
75
|
+
};
|
|
72
76
|
const globalServices$1 = {
|
|
73
77
|
sizingGlobalService: Symbol('sizingGlobalService'),
|
|
74
78
|
riskGlobalService: Symbol('riskGlobalService'),
|
|
@@ -134,6 +138,7 @@ const TYPES = {
|
|
|
134
138
|
...connectionServices$1,
|
|
135
139
|
...schemaServices$1,
|
|
136
140
|
...coreServices$1,
|
|
141
|
+
...metaServices$1,
|
|
137
142
|
...globalServices$1,
|
|
138
143
|
...commandServices$1,
|
|
139
144
|
...logicPrivateServices$1,
|
|
@@ -3538,19 +3543,6 @@ const beginTime = (run) => (...args) => {
|
|
|
3538
3543
|
return fn();
|
|
3539
3544
|
};
|
|
3540
3545
|
|
|
3541
|
-
/**
|
|
3542
|
-
* Retrieves the current timestamp for debugging purposes.
|
|
3543
|
-
* 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.
|
|
3544
|
-
* Can be empty (undefined) if not called from strategy async context, as it's intended for debugging and not critical for logic.
|
|
3545
|
-
* @return {number | undefined} The current timestamp in milliseconds from the execution context, or undefined if not available.
|
|
3546
|
-
*/
|
|
3547
|
-
const getDebugTimestamp = () => {
|
|
3548
|
-
if (ExecutionContextService.hasContext()) {
|
|
3549
|
-
return bt.executionContextService.context.when.getTime();
|
|
3550
|
-
}
|
|
3551
|
-
return undefined;
|
|
3552
|
-
};
|
|
3553
|
-
|
|
3554
3546
|
const INTERVAL_MINUTES$6 = {
|
|
3555
3547
|
"1m": 1,
|
|
3556
3548
|
"3m": 3,
|
|
@@ -4258,7 +4250,7 @@ const GET_SIGNAL_FN = trycatch(async (self) => {
|
|
|
4258
4250
|
pendingAt: currentTime, // Для immediate signal оба времени одинаковые
|
|
4259
4251
|
timestamp: currentTime,
|
|
4260
4252
|
_isScheduled: false,
|
|
4261
|
-
_entry: [{ price: signal.priceOpen, cost: signal.cost ?? GLOBAL_CONFIG.CC_POSITION_ENTRY_COST,
|
|
4253
|
+
_entry: [{ price: signal.priceOpen, cost: signal.cost ?? GLOBAL_CONFIG.CC_POSITION_ENTRY_COST, timestamp: currentTime }],
|
|
4262
4254
|
};
|
|
4263
4255
|
// Валидируем сигнал перед возвратом
|
|
4264
4256
|
VALIDATE_SIGNAL_FN(signalRow, currentPrice, false);
|
|
@@ -4282,7 +4274,7 @@ const GET_SIGNAL_FN = trycatch(async (self) => {
|
|
|
4282
4274
|
pendingAt: SCHEDULED_SIGNAL_PENDING_MOCK, // Временно, обновится при активации
|
|
4283
4275
|
timestamp: currentTime,
|
|
4284
4276
|
_isScheduled: true,
|
|
4285
|
-
_entry: [{ price: signal.priceOpen, cost: signal.cost ?? GLOBAL_CONFIG.CC_POSITION_ENTRY_COST,
|
|
4277
|
+
_entry: [{ price: signal.priceOpen, cost: signal.cost ?? GLOBAL_CONFIG.CC_POSITION_ENTRY_COST, timestamp: currentTime }],
|
|
4286
4278
|
};
|
|
4287
4279
|
// Валидируем сигнал перед возвратом
|
|
4288
4280
|
VALIDATE_SIGNAL_FN(scheduledSignalRow, currentPrice, true);
|
|
@@ -4302,7 +4294,7 @@ const GET_SIGNAL_FN = trycatch(async (self) => {
|
|
|
4302
4294
|
pendingAt: currentTime, // Для immediate signal оба времени одинаковые
|
|
4303
4295
|
timestamp: currentTime,
|
|
4304
4296
|
_isScheduled: false,
|
|
4305
|
-
_entry: [{ price: currentPrice, cost: signal.cost ?? GLOBAL_CONFIG.CC_POSITION_ENTRY_COST,
|
|
4297
|
+
_entry: [{ price: currentPrice, cost: signal.cost ?? GLOBAL_CONFIG.CC_POSITION_ENTRY_COST, timestamp: currentTime }],
|
|
4306
4298
|
};
|
|
4307
4299
|
// Валидируем сигнал перед возвратом
|
|
4308
4300
|
VALIDATE_SIGNAL_FN(signalRow, currentPrice, false);
|
|
@@ -4372,7 +4364,7 @@ const WAIT_FOR_DISPOSE_FN$1 = async (self) => {
|
|
|
4372
4364
|
self.params.logger.debug("ClientStrategy dispose");
|
|
4373
4365
|
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);
|
|
4374
4366
|
};
|
|
4375
|
-
const PARTIAL_PROFIT_FN = (self, signal, percentToClose, currentPrice) => {
|
|
4367
|
+
const PARTIAL_PROFIT_FN = (self, signal, percentToClose, currentPrice, timestamp) => {
|
|
4376
4368
|
// Initialize partial array if not present
|
|
4377
4369
|
if (!signal._partial)
|
|
4378
4370
|
signal._partial = [];
|
|
@@ -4401,7 +4393,7 @@ const PARTIAL_PROFIT_FN = (self, signal, percentToClose, currentPrice) => {
|
|
|
4401
4393
|
entryCountAtClose,
|
|
4402
4394
|
currentPrice,
|
|
4403
4395
|
costBasisAtClose: remainingCostBasis,
|
|
4404
|
-
|
|
4396
|
+
timestamp,
|
|
4405
4397
|
});
|
|
4406
4398
|
self.params.logger.info("PARTIAL_PROFIT_FN executed", {
|
|
4407
4399
|
signalId: signal.id,
|
|
@@ -4411,7 +4403,7 @@ const PARTIAL_PROFIT_FN = (self, signal, percentToClose, currentPrice) => {
|
|
|
4411
4403
|
});
|
|
4412
4404
|
return true;
|
|
4413
4405
|
};
|
|
4414
|
-
const PARTIAL_LOSS_FN = (self, signal, percentToClose, currentPrice) => {
|
|
4406
|
+
const PARTIAL_LOSS_FN = (self, signal, percentToClose, currentPrice, timestamp) => {
|
|
4415
4407
|
// Initialize partial array if not present
|
|
4416
4408
|
if (!signal._partial)
|
|
4417
4409
|
signal._partial = [];
|
|
@@ -4439,7 +4431,7 @@ const PARTIAL_LOSS_FN = (self, signal, percentToClose, currentPrice) => {
|
|
|
4439
4431
|
currentPrice,
|
|
4440
4432
|
entryCountAtClose,
|
|
4441
4433
|
costBasisAtClose: remainingCostBasis,
|
|
4442
|
-
|
|
4434
|
+
timestamp,
|
|
4443
4435
|
});
|
|
4444
4436
|
self.params.logger.warn("PARTIAL_LOSS_FN executed", {
|
|
4445
4437
|
signalId: signal.id,
|
|
@@ -4836,10 +4828,10 @@ const BREAKEVEN_FN = (self, signal, currentPrice) => {
|
|
|
4836
4828
|
});
|
|
4837
4829
|
return true;
|
|
4838
4830
|
};
|
|
4839
|
-
const AVERAGE_BUY_FN = (self, signal, currentPrice, cost = GLOBAL_CONFIG.CC_POSITION_ENTRY_COST) => {
|
|
4831
|
+
const AVERAGE_BUY_FN = (self, signal, currentPrice, timestamp, cost = GLOBAL_CONFIG.CC_POSITION_ENTRY_COST) => {
|
|
4840
4832
|
// Ensure _entry is initialized (handles signals loaded from disk without _entry)
|
|
4841
4833
|
if (!signal._entry || signal._entry.length === 0) {
|
|
4842
|
-
signal._entry = [{ price: signal.priceOpen, cost: GLOBAL_CONFIG.CC_POSITION_ENTRY_COST,
|
|
4834
|
+
signal._entry = [{ price: signal.priceOpen, cost: GLOBAL_CONFIG.CC_POSITION_ENTRY_COST, timestamp }];
|
|
4843
4835
|
}
|
|
4844
4836
|
if (signal.position === "long") {
|
|
4845
4837
|
// LONG: new entry must beat the all-time low — strictly below every prior entry price
|
|
@@ -4869,7 +4861,7 @@ const AVERAGE_BUY_FN = (self, signal, currentPrice, cost = GLOBAL_CONFIG.CC_POSI
|
|
|
4869
4861
|
return false;
|
|
4870
4862
|
}
|
|
4871
4863
|
}
|
|
4872
|
-
signal._entry.push({ price: currentPrice, cost,
|
|
4864
|
+
signal._entry.push({ price: currentPrice, cost, timestamp });
|
|
4873
4865
|
self.params.logger.info("AVERAGE_BUY_FN executed", {
|
|
4874
4866
|
signalId: signal.id,
|
|
4875
4867
|
position: signal.position,
|
|
@@ -6654,16 +6646,16 @@ class ClientStrategy {
|
|
|
6654
6646
|
* // No DCA: [{ price: 43000, cost: 100 }]
|
|
6655
6647
|
* // One DCA: [{ price: 43000, cost: 100 }, { price: 42000, cost: 100 }]
|
|
6656
6648
|
*/
|
|
6657
|
-
async getPositionEntries(symbol) {
|
|
6649
|
+
async getPositionEntries(symbol, timestamp) {
|
|
6658
6650
|
this.params.logger.debug("ClientStrategy getPositionEntries", { symbol });
|
|
6659
6651
|
if (!this._pendingSignal) {
|
|
6660
6652
|
return null;
|
|
6661
6653
|
}
|
|
6662
6654
|
const entries = this._pendingSignal._entry;
|
|
6663
6655
|
if (!entries || entries.length === 0) {
|
|
6664
|
-
return [{ price: this._pendingSignal.priceOpen, cost: GLOBAL_CONFIG.CC_POSITION_ENTRY_COST }];
|
|
6656
|
+
return [{ price: this._pendingSignal.priceOpen, cost: GLOBAL_CONFIG.CC_POSITION_ENTRY_COST, timestamp }];
|
|
6665
6657
|
}
|
|
6666
|
-
return entries.map(({ price, cost }) => ({ price, cost }));
|
|
6658
|
+
return entries.map(({ price, cost, timestamp }) => ({ price, cost, timestamp }));
|
|
6667
6659
|
}
|
|
6668
6660
|
/**
|
|
6669
6661
|
* Performs a single tick of strategy execution.
|
|
@@ -7499,7 +7491,7 @@ class ClientStrategy {
|
|
|
7499
7491
|
* // success3 = false (skipped, would exceed 100%)
|
|
7500
7492
|
* ```
|
|
7501
7493
|
*/
|
|
7502
|
-
async partialProfit(symbol, percentToClose, currentPrice, backtest) {
|
|
7494
|
+
async partialProfit(symbol, percentToClose, currentPrice, backtest, timestamp) {
|
|
7503
7495
|
this.params.logger.debug("ClientStrategy partialProfit", {
|
|
7504
7496
|
symbol,
|
|
7505
7497
|
percentToClose,
|
|
@@ -7563,7 +7555,7 @@ class ClientStrategy {
|
|
|
7563
7555
|
return false;
|
|
7564
7556
|
}
|
|
7565
7557
|
// Execute partial close logic
|
|
7566
|
-
const wasExecuted = PARTIAL_PROFIT_FN(this, this._pendingSignal, percentToClose, currentPrice);
|
|
7558
|
+
const wasExecuted = PARTIAL_PROFIT_FN(this, this._pendingSignal, percentToClose, currentPrice, timestamp);
|
|
7567
7559
|
// If partial was not executed (exceeded 100%), return false without persistence
|
|
7568
7560
|
if (!wasExecuted) {
|
|
7569
7561
|
return false;
|
|
@@ -7682,7 +7674,7 @@ class ClientStrategy {
|
|
|
7682
7674
|
* // success3 = false (skipped, would exceed 100%)
|
|
7683
7675
|
* ```
|
|
7684
7676
|
*/
|
|
7685
|
-
async partialLoss(symbol, percentToClose, currentPrice, backtest) {
|
|
7677
|
+
async partialLoss(symbol, percentToClose, currentPrice, backtest, timestamp) {
|
|
7686
7678
|
this.params.logger.debug("ClientStrategy partialLoss", {
|
|
7687
7679
|
symbol,
|
|
7688
7680
|
percentToClose,
|
|
@@ -7746,7 +7738,7 @@ class ClientStrategy {
|
|
|
7746
7738
|
return false;
|
|
7747
7739
|
}
|
|
7748
7740
|
// Execute partial close logic
|
|
7749
|
-
const wasExecuted = PARTIAL_LOSS_FN(this, this._pendingSignal, percentToClose, currentPrice);
|
|
7741
|
+
const wasExecuted = PARTIAL_LOSS_FN(this, this._pendingSignal, percentToClose, currentPrice, timestamp);
|
|
7750
7742
|
// If partial was not executed (exceeded 100%), return false without persistence
|
|
7751
7743
|
if (!wasExecuted) {
|
|
7752
7744
|
return false;
|
|
@@ -8502,7 +8494,7 @@ class ClientStrategy {
|
|
|
8502
8494
|
* @param backtest - Whether running in backtest mode
|
|
8503
8495
|
* @returns Promise<boolean> - true if entry added, false if rejected by direction check
|
|
8504
8496
|
*/
|
|
8505
|
-
async averageBuy(symbol, currentPrice, backtest, cost = GLOBAL_CONFIG.CC_POSITION_ENTRY_COST) {
|
|
8497
|
+
async averageBuy(symbol, currentPrice, backtest, timestamp, cost = GLOBAL_CONFIG.CC_POSITION_ENTRY_COST) {
|
|
8506
8498
|
this.params.logger.debug("ClientStrategy averageBuy", {
|
|
8507
8499
|
symbol,
|
|
8508
8500
|
currentPrice,
|
|
@@ -8517,7 +8509,7 @@ class ClientStrategy {
|
|
|
8517
8509
|
throw new Error(`ClientStrategy averageBuy: currentPrice must be a positive finite number, got ${currentPrice}`);
|
|
8518
8510
|
}
|
|
8519
8511
|
// Execute averaging logic
|
|
8520
|
-
const result = AVERAGE_BUY_FN(this, this._pendingSignal, currentPrice, cost);
|
|
8512
|
+
const result = AVERAGE_BUY_FN(this, this._pendingSignal, currentPrice, timestamp, cost);
|
|
8521
8513
|
if (!result) {
|
|
8522
8514
|
return false;
|
|
8523
8515
|
}
|
|
@@ -8981,7 +8973,7 @@ const GET_RISK_FN = (dto, backtest, exchangeName, frameName, self) => {
|
|
|
8981
8973
|
* @param backtest - Whether running in backtest mode
|
|
8982
8974
|
* @returns Unique string key for memoization
|
|
8983
8975
|
*/
|
|
8984
|
-
const CREATE_KEY_FN$
|
|
8976
|
+
const CREATE_KEY_FN$o = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
8985
8977
|
const parts = [symbol, strategyName, exchangeName];
|
|
8986
8978
|
if (frameName)
|
|
8987
8979
|
parts.push(frameName);
|
|
@@ -9158,6 +9150,8 @@ class StrategyConnectionService {
|
|
|
9158
9150
|
this.partialConnectionService = inject(TYPES.partialConnectionService);
|
|
9159
9151
|
this.breakevenConnectionService = inject(TYPES.breakevenConnectionService);
|
|
9160
9152
|
this.actionCoreService = inject(TYPES.actionCoreService);
|
|
9153
|
+
this.timeMetaService = inject(TYPES.timeMetaService);
|
|
9154
|
+
this.priceMetaService = inject(TYPES.priceMetaService);
|
|
9161
9155
|
/**
|
|
9162
9156
|
* Retrieves memoized ClientStrategy instance for given symbol-strategy pair with exchange and frame isolation.
|
|
9163
9157
|
*
|
|
@@ -9171,7 +9165,7 @@ class StrategyConnectionService {
|
|
|
9171
9165
|
* @param backtest - Whether running in backtest mode
|
|
9172
9166
|
* @returns Configured ClientStrategy instance
|
|
9173
9167
|
*/
|
|
9174
|
-
this.getStrategy = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
9168
|
+
this.getStrategy = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$o(symbol, strategyName, exchangeName, frameName, backtest), (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
9175
9169
|
const { riskName = "", riskList = [], getSignal, interval, callbacks, } = this.strategySchemaService.get(strategyName);
|
|
9176
9170
|
return new ClientStrategy({
|
|
9177
9171
|
symbol,
|
|
@@ -9258,6 +9252,20 @@ class StrategyConnectionService {
|
|
|
9258
9252
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9259
9253
|
return await strategy.getTotalCostClosed(symbol);
|
|
9260
9254
|
};
|
|
9255
|
+
/**
|
|
9256
|
+
* Returns the effective (DCA-averaged) entry price for the current pending signal.
|
|
9257
|
+
*
|
|
9258
|
+
* This is the harmonic mean of all _entry prices, which is the correct
|
|
9259
|
+
* cost-basis price used in all PNL calculations.
|
|
9260
|
+
* With no DCA entries, equals the original priceOpen.
|
|
9261
|
+
*
|
|
9262
|
+
* Returns null if no pending signal exists.
|
|
9263
|
+
*
|
|
9264
|
+
* @param backtest - Whether running in backtest mode
|
|
9265
|
+
* @param symbol - Trading pair symbol
|
|
9266
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9267
|
+
* @returns Promise resolving to effective entry price or null
|
|
9268
|
+
*/
|
|
9261
9269
|
this.getPositionAveragePrice = async (backtest, symbol, context) => {
|
|
9262
9270
|
this.loggerService.log("strategyConnectionService getPositionAveragePrice", {
|
|
9263
9271
|
symbol,
|
|
@@ -9267,6 +9275,19 @@ class StrategyConnectionService {
|
|
|
9267
9275
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9268
9276
|
return await strategy.getPositionAveragePrice(symbol);
|
|
9269
9277
|
};
|
|
9278
|
+
/**
|
|
9279
|
+
* Returns the number of DCA entries made for the current pending signal.
|
|
9280
|
+
*
|
|
9281
|
+
* 1 = original entry only (no DCA).
|
|
9282
|
+
* Increases by 1 with each successful commitAverageBuy().
|
|
9283
|
+
*
|
|
9284
|
+
* Returns null if no pending signal exists.
|
|
9285
|
+
*
|
|
9286
|
+
* @param backtest - Whether running in backtest mode
|
|
9287
|
+
* @param symbol - Trading pair symbol
|
|
9288
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9289
|
+
* @returns Promise resolving to entry count or null
|
|
9290
|
+
*/
|
|
9270
9291
|
this.getPositionInvestedCount = async (backtest, symbol, context) => {
|
|
9271
9292
|
this.loggerService.log("strategyConnectionService getPositionInvestedCount", {
|
|
9272
9293
|
symbol,
|
|
@@ -9276,6 +9297,19 @@ class StrategyConnectionService {
|
|
|
9276
9297
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9277
9298
|
return await strategy.getPositionInvestedCount(symbol);
|
|
9278
9299
|
};
|
|
9300
|
+
/**
|
|
9301
|
+
* Returns the total invested cost basis in dollars for the current pending signal.
|
|
9302
|
+
*
|
|
9303
|
+
* Equal to entryCount × $100 (COST_BASIS_PER_ENTRY).
|
|
9304
|
+
* 1 entry = $100, 2 entries = $200, etc.
|
|
9305
|
+
*
|
|
9306
|
+
* Returns null if no pending signal exists.
|
|
9307
|
+
*
|
|
9308
|
+
* @param backtest - Whether running in backtest mode
|
|
9309
|
+
* @param symbol - Trading pair symbol
|
|
9310
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9311
|
+
* @returns Promise resolving to total invested cost in dollars or null
|
|
9312
|
+
*/
|
|
9279
9313
|
this.getPositionInvestedCost = async (backtest, symbol, context) => {
|
|
9280
9314
|
this.loggerService.log("strategyConnectionService getPositionInvestedCost", {
|
|
9281
9315
|
symbol,
|
|
@@ -9285,6 +9319,20 @@ class StrategyConnectionService {
|
|
|
9285
9319
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9286
9320
|
return await strategy.getPositionInvestedCost(symbol);
|
|
9287
9321
|
};
|
|
9322
|
+
/**
|
|
9323
|
+
* Returns the unrealized PNL percentage for the current pending signal at currentPrice.
|
|
9324
|
+
*
|
|
9325
|
+
* Accounts for partial closes, DCA entries, slippage and fees
|
|
9326
|
+
* (delegates to toProfitLossDto).
|
|
9327
|
+
*
|
|
9328
|
+
* Returns null if no pending signal exists.
|
|
9329
|
+
*
|
|
9330
|
+
* @param backtest - Whether running in backtest mode
|
|
9331
|
+
* @param symbol - Trading pair symbol
|
|
9332
|
+
* @param currentPrice - Current market price
|
|
9333
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9334
|
+
* @returns Promise resolving to pnlPercentage or null
|
|
9335
|
+
*/
|
|
9288
9336
|
this.getPositionPnlPercent = async (backtest, symbol, currentPrice, context) => {
|
|
9289
9337
|
this.loggerService.log("strategyConnectionService getPositionPnlPercent", {
|
|
9290
9338
|
symbol,
|
|
@@ -9295,6 +9343,20 @@ class StrategyConnectionService {
|
|
|
9295
9343
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9296
9344
|
return await strategy.getPositionPnlPercent(symbol, currentPrice);
|
|
9297
9345
|
};
|
|
9346
|
+
/**
|
|
9347
|
+
* Returns the unrealized PNL in dollars for the current pending signal at currentPrice.
|
|
9348
|
+
*
|
|
9349
|
+
* Calculated as: pnlPercentage / 100 × totalInvestedCost
|
|
9350
|
+
* Accounts for partial closes, DCA entries, slippage and fees.
|
|
9351
|
+
*
|
|
9352
|
+
* Returns null if no pending signal exists.
|
|
9353
|
+
*
|
|
9354
|
+
* @param backtest - Whether running in backtest mode
|
|
9355
|
+
* @param symbol - Trading pair symbol
|
|
9356
|
+
* @param currentPrice - Current market price
|
|
9357
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9358
|
+
* @returns Promise resolving to pnl in dollars or null
|
|
9359
|
+
*/
|
|
9298
9360
|
this.getPositionPnlCost = async (backtest, symbol, currentPrice, context) => {
|
|
9299
9361
|
this.loggerService.log("strategyConnectionService getPositionPnlCost", {
|
|
9300
9362
|
symbol,
|
|
@@ -9305,6 +9367,27 @@ class StrategyConnectionService {
|
|
|
9305
9367
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9306
9368
|
return await strategy.getPositionPnlCost(symbol, currentPrice);
|
|
9307
9369
|
};
|
|
9370
|
+
/**
|
|
9371
|
+
* Returns the list of DCA entry prices for the current pending signal.
|
|
9372
|
+
*
|
|
9373
|
+
* The first element is always the original priceOpen (initial entry).
|
|
9374
|
+
* Each subsequent element is a price added by commitAverageBuy().
|
|
9375
|
+
*
|
|
9376
|
+
* Returns null if no pending signal exists.
|
|
9377
|
+
* Returns a single-element array [priceOpen] if no DCA entries were made.
|
|
9378
|
+
*
|
|
9379
|
+
* @param backtest - Whether running in backtest mode
|
|
9380
|
+
* @param symbol - Trading pair symbol
|
|
9381
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9382
|
+
* @returns Promise resolving to array of entry prices or null
|
|
9383
|
+
*
|
|
9384
|
+
* @example
|
|
9385
|
+
* ```typescript
|
|
9386
|
+
* // No DCA: [43000]
|
|
9387
|
+
* // One DCA: [43000, 42000]
|
|
9388
|
+
* // Two DCA: [43000, 42000, 41500]
|
|
9389
|
+
* ```
|
|
9390
|
+
*/
|
|
9308
9391
|
this.getPositionLevels = async (backtest, symbol, context) => {
|
|
9309
9392
|
this.loggerService.log("strategyConnectionService getPositionLevels", {
|
|
9310
9393
|
symbol,
|
|
@@ -9314,6 +9397,20 @@ class StrategyConnectionService {
|
|
|
9314
9397
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9315
9398
|
return await strategy.getPositionLevels(symbol);
|
|
9316
9399
|
};
|
|
9400
|
+
/**
|
|
9401
|
+
* Returns the list of partial closes for the current pending signal.
|
|
9402
|
+
*
|
|
9403
|
+
* Each entry records a partial profit or loss close event with its type,
|
|
9404
|
+
* percent closed, price at close, cost basis snapshot, and entry count at close.
|
|
9405
|
+
*
|
|
9406
|
+
* Returns null if no pending signal exists.
|
|
9407
|
+
* Returns an empty array if no partial closes have been executed.
|
|
9408
|
+
*
|
|
9409
|
+
* @param backtest - Whether running in backtest mode
|
|
9410
|
+
* @param symbol - Trading pair symbol
|
|
9411
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9412
|
+
* @returns Promise resolving to array of partial close records or null
|
|
9413
|
+
*/
|
|
9317
9414
|
this.getPositionPartials = async (backtest, symbol, context) => {
|
|
9318
9415
|
this.loggerService.log("strategyConnectionService getPositionPartials", {
|
|
9319
9416
|
symbol,
|
|
@@ -9323,6 +9420,27 @@ class StrategyConnectionService {
|
|
|
9323
9420
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9324
9421
|
return await strategy.getPositionPartials(symbol);
|
|
9325
9422
|
};
|
|
9423
|
+
/**
|
|
9424
|
+
* Returns the list of DCA entry prices and costs for the current pending signal.
|
|
9425
|
+
*
|
|
9426
|
+
* Each entry records the price and cost of a single position entry.
|
|
9427
|
+
* The first element is always the original priceOpen (initial entry).
|
|
9428
|
+
* Each subsequent element is an entry added by averageBuy().
|
|
9429
|
+
*
|
|
9430
|
+
* Returns null if no pending signal exists.
|
|
9431
|
+
* Returns a single-element array [{ price: priceOpen, cost }] if no DCA entries were made.
|
|
9432
|
+
*
|
|
9433
|
+
* @param backtest - Whether running in backtest mode
|
|
9434
|
+
* @param symbol - Trading pair symbol
|
|
9435
|
+
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9436
|
+
* @returns Promise resolving to array of entry records or null
|
|
9437
|
+
*
|
|
9438
|
+
* @example
|
|
9439
|
+
* ```typescript
|
|
9440
|
+
* // No DCA: [{ price: 43000, cost: 100 }]
|
|
9441
|
+
* // One DCA: [{ price: 43000, cost: 100 }, { price: 42000, cost: 100 }]
|
|
9442
|
+
* ```
|
|
9443
|
+
*/
|
|
9326
9444
|
this.getPositionEntries = async (backtest, symbol, context) => {
|
|
9327
9445
|
this.loggerService.log("strategyConnectionService getPositionEntries", {
|
|
9328
9446
|
symbol,
|
|
@@ -9330,7 +9448,8 @@ class StrategyConnectionService {
|
|
|
9330
9448
|
backtest,
|
|
9331
9449
|
});
|
|
9332
9450
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9333
|
-
|
|
9451
|
+
const timestamp = await this.timeMetaService.getTimestamp(symbol, context, backtest);
|
|
9452
|
+
return await strategy.getPositionEntries(symbol, timestamp);
|
|
9334
9453
|
};
|
|
9335
9454
|
/**
|
|
9336
9455
|
* Retrieves the currently active scheduled signal for the strategy.
|
|
@@ -9432,6 +9551,10 @@ class StrategyConnectionService {
|
|
|
9432
9551
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9433
9552
|
await strategy.waitForInit();
|
|
9434
9553
|
const tick = await strategy.tick(symbol, context.strategyName);
|
|
9554
|
+
{
|
|
9555
|
+
this.priceMetaService.next(symbol, tick.currentPrice, context, backtest);
|
|
9556
|
+
this.timeMetaService.next(symbol, tick.createdAt, context, backtest);
|
|
9557
|
+
}
|
|
9435
9558
|
{
|
|
9436
9559
|
await CALL_SIGNAL_EMIT_FN(this, tick, context, backtest, symbol);
|
|
9437
9560
|
}
|
|
@@ -9538,7 +9661,7 @@ class StrategyConnectionService {
|
|
|
9538
9661
|
}
|
|
9539
9662
|
return;
|
|
9540
9663
|
}
|
|
9541
|
-
const key = CREATE_KEY_FN$
|
|
9664
|
+
const key = CREATE_KEY_FN$o(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
9542
9665
|
if (!this.getStrategy.has(key)) {
|
|
9543
9666
|
return;
|
|
9544
9667
|
}
|
|
@@ -9607,9 +9730,9 @@ class StrategyConnectionService {
|
|
|
9607
9730
|
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9608
9731
|
* @returns Promise<boolean> - true if `partialProfit` would execute, false otherwise
|
|
9609
9732
|
*/
|
|
9610
|
-
this.validatePartialProfit = (backtest, symbol, percentToClose, currentPrice, context) => {
|
|
9733
|
+
this.validatePartialProfit = async (backtest, symbol, percentToClose, currentPrice, context) => {
|
|
9611
9734
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9612
|
-
return
|
|
9735
|
+
return await strategy.validatePartialProfit(symbol, percentToClose, currentPrice);
|
|
9613
9736
|
};
|
|
9614
9737
|
/**
|
|
9615
9738
|
* Executes partial close at profit level (moving toward TP).
|
|
@@ -9650,7 +9773,8 @@ class StrategyConnectionService {
|
|
|
9650
9773
|
backtest,
|
|
9651
9774
|
});
|
|
9652
9775
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9653
|
-
|
|
9776
|
+
const timestamp = await this.timeMetaService.getTimestamp(symbol, context, backtest);
|
|
9777
|
+
return await strategy.partialProfit(symbol, percentToClose, currentPrice, backtest, timestamp);
|
|
9654
9778
|
};
|
|
9655
9779
|
/**
|
|
9656
9780
|
* Checks whether `partialLoss` would succeed without executing it.
|
|
@@ -9663,9 +9787,9 @@ class StrategyConnectionService {
|
|
|
9663
9787
|
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9664
9788
|
* @returns Promise<boolean> - true if `partialLoss` would execute, false otherwise
|
|
9665
9789
|
*/
|
|
9666
|
-
this.validatePartialLoss = (backtest, symbol, percentToClose, currentPrice, context) => {
|
|
9790
|
+
this.validatePartialLoss = async (backtest, symbol, percentToClose, currentPrice, context) => {
|
|
9667
9791
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9668
|
-
return
|
|
9792
|
+
return await strategy.validatePartialLoss(symbol, percentToClose, currentPrice);
|
|
9669
9793
|
};
|
|
9670
9794
|
/**
|
|
9671
9795
|
* Executes partial close at loss level (moving toward SL).
|
|
@@ -9706,7 +9830,8 @@ class StrategyConnectionService {
|
|
|
9706
9830
|
backtest,
|
|
9707
9831
|
});
|
|
9708
9832
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9709
|
-
|
|
9833
|
+
const timestamp = await this.timeMetaService.getTimestamp(symbol, context, backtest);
|
|
9834
|
+
return await strategy.partialLoss(symbol, percentToClose, currentPrice, backtest, timestamp);
|
|
9710
9835
|
};
|
|
9711
9836
|
/**
|
|
9712
9837
|
* Checks whether `trailingStop` would succeed without executing it.
|
|
@@ -9719,9 +9844,9 @@ class StrategyConnectionService {
|
|
|
9719
9844
|
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9720
9845
|
* @returns Promise<boolean> - true if `trailingStop` would execute, false otherwise
|
|
9721
9846
|
*/
|
|
9722
|
-
this.validateTrailingStop = (backtest, symbol, percentShift, currentPrice, context) => {
|
|
9847
|
+
this.validateTrailingStop = async (backtest, symbol, percentShift, currentPrice, context) => {
|
|
9723
9848
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9724
|
-
return
|
|
9849
|
+
return await strategy.validateTrailingStop(symbol, percentShift, currentPrice);
|
|
9725
9850
|
};
|
|
9726
9851
|
/**
|
|
9727
9852
|
* Adjusts the trailing stop-loss distance for an active pending signal.
|
|
@@ -9773,9 +9898,9 @@ class StrategyConnectionService {
|
|
|
9773
9898
|
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9774
9899
|
* @returns Promise<boolean> - true if `trailingTake` would execute, false otherwise
|
|
9775
9900
|
*/
|
|
9776
|
-
this.validateTrailingTake = (backtest, symbol, percentShift, currentPrice, context) => {
|
|
9901
|
+
this.validateTrailingTake = async (backtest, symbol, percentShift, currentPrice, context) => {
|
|
9777
9902
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9778
|
-
return
|
|
9903
|
+
return await strategy.validateTrailingTake(symbol, percentShift, currentPrice);
|
|
9779
9904
|
};
|
|
9780
9905
|
/**
|
|
9781
9906
|
* Adjusts the trailing take-profit distance for an active pending signal.
|
|
@@ -9826,9 +9951,9 @@ class StrategyConnectionService {
|
|
|
9826
9951
|
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9827
9952
|
* @returns Promise<boolean> - true if `breakeven` would execute, false otherwise
|
|
9828
9953
|
*/
|
|
9829
|
-
this.validateBreakeven = (backtest, symbol, currentPrice, context) => {
|
|
9954
|
+
this.validateBreakeven = async (backtest, symbol, currentPrice, context) => {
|
|
9830
9955
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9831
|
-
return
|
|
9956
|
+
return await strategy.validateBreakeven(symbol, currentPrice);
|
|
9832
9957
|
};
|
|
9833
9958
|
/**
|
|
9834
9959
|
* Delegates to ClientStrategy.breakeven() with current execution context.
|
|
@@ -9905,9 +10030,9 @@ class StrategyConnectionService {
|
|
|
9905
10030
|
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
9906
10031
|
* @returns Promise<boolean> - true if `averageBuy` would execute, false otherwise
|
|
9907
10032
|
*/
|
|
9908
|
-
this.validateAverageBuy = (backtest, symbol, currentPrice, context) => {
|
|
10033
|
+
this.validateAverageBuy = async (backtest, symbol, currentPrice, context) => {
|
|
9909
10034
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9910
|
-
return
|
|
10035
|
+
return await strategy.validateAverageBuy(symbol, currentPrice);
|
|
9911
10036
|
};
|
|
9912
10037
|
/**
|
|
9913
10038
|
* Adds a new DCA entry to the active pending signal.
|
|
@@ -9928,7 +10053,8 @@ class StrategyConnectionService {
|
|
|
9928
10053
|
backtest,
|
|
9929
10054
|
});
|
|
9930
10055
|
const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
9931
|
-
|
|
10056
|
+
const timestamp = await this.timeMetaService.getTimestamp(symbol, context, backtest);
|
|
10057
|
+
return await strategy.averageBuy(symbol, currentPrice, backtest, timestamp, cost);
|
|
9932
10058
|
};
|
|
9933
10059
|
}
|
|
9934
10060
|
}
|
|
@@ -10669,7 +10795,7 @@ class ClientRisk {
|
|
|
10669
10795
|
* @param backtest - Whether running in backtest mode
|
|
10670
10796
|
* @returns Unique string key for memoization
|
|
10671
10797
|
*/
|
|
10672
|
-
const CREATE_KEY_FN$
|
|
10798
|
+
const CREATE_KEY_FN$n = (riskName, exchangeName, frameName, backtest) => {
|
|
10673
10799
|
const parts = [riskName, exchangeName];
|
|
10674
10800
|
if (frameName)
|
|
10675
10801
|
parts.push(frameName);
|
|
@@ -10768,7 +10894,7 @@ class RiskConnectionService {
|
|
|
10768
10894
|
* @param backtest - True if backtest mode, false if live mode
|
|
10769
10895
|
* @returns Configured ClientRisk instance
|
|
10770
10896
|
*/
|
|
10771
|
-
this.getRisk = memoize(([riskName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
10897
|
+
this.getRisk = memoize(([riskName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$n(riskName, exchangeName, frameName, backtest), (riskName, exchangeName, frameName, backtest) => {
|
|
10772
10898
|
const schema = this.riskSchemaService.get(riskName);
|
|
10773
10899
|
return new ClientRisk({
|
|
10774
10900
|
...schema,
|
|
@@ -10836,7 +10962,7 @@ class RiskConnectionService {
|
|
|
10836
10962
|
payload,
|
|
10837
10963
|
});
|
|
10838
10964
|
if (payload) {
|
|
10839
|
-
const key = CREATE_KEY_FN$
|
|
10965
|
+
const key = CREATE_KEY_FN$n(payload.riskName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
10840
10966
|
this.getRisk.clear(key);
|
|
10841
10967
|
}
|
|
10842
10968
|
else {
|
|
@@ -12303,7 +12429,7 @@ class ClientAction {
|
|
|
12303
12429
|
* @param backtest - Whether running in backtest mode
|
|
12304
12430
|
* @returns Unique string key for memoization
|
|
12305
12431
|
*/
|
|
12306
|
-
const CREATE_KEY_FN$
|
|
12432
|
+
const CREATE_KEY_FN$m = (actionName, strategyName, exchangeName, frameName, backtest) => {
|
|
12307
12433
|
const parts = [actionName, strategyName, exchangeName];
|
|
12308
12434
|
if (frameName)
|
|
12309
12435
|
parts.push(frameName);
|
|
@@ -12354,7 +12480,7 @@ class ActionConnectionService {
|
|
|
12354
12480
|
* @param backtest - True if backtest mode, false if live mode
|
|
12355
12481
|
* @returns Configured ClientAction instance
|
|
12356
12482
|
*/
|
|
12357
|
-
this.getAction = memoize(([actionName, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
12483
|
+
this.getAction = memoize(([actionName, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$m(actionName, strategyName, exchangeName, frameName, backtest), (actionName, strategyName, exchangeName, frameName, backtest) => {
|
|
12358
12484
|
const schema = this.actionSchemaService.get(actionName);
|
|
12359
12485
|
return new ClientAction({
|
|
12360
12486
|
...schema,
|
|
@@ -12564,7 +12690,7 @@ class ActionConnectionService {
|
|
|
12564
12690
|
await Promise.all(actions.map(async (action) => await action.dispose()));
|
|
12565
12691
|
return;
|
|
12566
12692
|
}
|
|
12567
|
-
const key = CREATE_KEY_FN$
|
|
12693
|
+
const key = CREATE_KEY_FN$m(payload.actionName, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
12568
12694
|
if (!this.getAction.has(key)) {
|
|
12569
12695
|
return;
|
|
12570
12696
|
}
|
|
@@ -12582,7 +12708,7 @@ const METHOD_NAME_VALIDATE$2 = "exchangeCoreService validate";
|
|
|
12582
12708
|
* @param exchangeName - Exchange name
|
|
12583
12709
|
* @returns Unique string key for memoization
|
|
12584
12710
|
*/
|
|
12585
|
-
const CREATE_KEY_FN$
|
|
12711
|
+
const CREATE_KEY_FN$l = (exchangeName) => {
|
|
12586
12712
|
return exchangeName;
|
|
12587
12713
|
};
|
|
12588
12714
|
/**
|
|
@@ -12606,7 +12732,7 @@ class ExchangeCoreService {
|
|
|
12606
12732
|
* @param exchangeName - Name of the exchange to validate
|
|
12607
12733
|
* @returns Promise that resolves when validation is complete
|
|
12608
12734
|
*/
|
|
12609
|
-
this.validate = memoize(([exchangeName]) => CREATE_KEY_FN$
|
|
12735
|
+
this.validate = memoize(([exchangeName]) => CREATE_KEY_FN$l(exchangeName), async (exchangeName) => {
|
|
12610
12736
|
this.loggerService.log(METHOD_NAME_VALIDATE$2, {
|
|
12611
12737
|
exchangeName,
|
|
12612
12738
|
});
|
|
@@ -12858,7 +12984,7 @@ const METHOD_NAME_VALIDATE$1 = "strategyCoreService validate";
|
|
|
12858
12984
|
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
12859
12985
|
* @returns Unique string key for memoization
|
|
12860
12986
|
*/
|
|
12861
|
-
const CREATE_KEY_FN$
|
|
12987
|
+
const CREATE_KEY_FN$k = (context) => {
|
|
12862
12988
|
const parts = [context.strategyName, context.exchangeName];
|
|
12863
12989
|
if (context.frameName)
|
|
12864
12990
|
parts.push(context.frameName);
|
|
@@ -12890,7 +13016,7 @@ class StrategyCoreService {
|
|
|
12890
13016
|
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
12891
13017
|
* @returns Promise that resolves when validation is complete
|
|
12892
13018
|
*/
|
|
12893
|
-
this.validate = memoize(([context]) => CREATE_KEY_FN$
|
|
13019
|
+
this.validate = memoize(([context]) => CREATE_KEY_FN$k(context), async (context) => {
|
|
12894
13020
|
this.loggerService.log(METHOD_NAME_VALIDATE$1, {
|
|
12895
13021
|
context,
|
|
12896
13022
|
});
|
|
@@ -13725,7 +13851,7 @@ class SizingGlobalService {
|
|
|
13725
13851
|
* @param context - Context with riskName, exchangeName, frameName
|
|
13726
13852
|
* @returns Unique string key for memoization
|
|
13727
13853
|
*/
|
|
13728
|
-
const CREATE_KEY_FN$
|
|
13854
|
+
const CREATE_KEY_FN$j = (context) => {
|
|
13729
13855
|
const parts = [context.riskName, context.exchangeName];
|
|
13730
13856
|
if (context.frameName)
|
|
13731
13857
|
parts.push(context.frameName);
|
|
@@ -13751,7 +13877,7 @@ class RiskGlobalService {
|
|
|
13751
13877
|
* @param payload - Payload with riskName, exchangeName and frameName
|
|
13752
13878
|
* @returns Promise that resolves when validation is complete
|
|
13753
13879
|
*/
|
|
13754
|
-
this.validate = memoize(([context]) => CREATE_KEY_FN$
|
|
13880
|
+
this.validate = memoize(([context]) => CREATE_KEY_FN$j(context), async (context) => {
|
|
13755
13881
|
this.loggerService.log("riskGlobalService validate", {
|
|
13756
13882
|
context,
|
|
13757
13883
|
});
|
|
@@ -13829,7 +13955,7 @@ const METHOD_NAME_VALIDATE = "actionCoreService validate";
|
|
|
13829
13955
|
* @param context - Execution context with strategyName, exchangeName, frameName
|
|
13830
13956
|
* @returns Unique string key for memoization
|
|
13831
13957
|
*/
|
|
13832
|
-
const CREATE_KEY_FN$
|
|
13958
|
+
const CREATE_KEY_FN$i = (context) => {
|
|
13833
13959
|
const parts = [context.strategyName, context.exchangeName];
|
|
13834
13960
|
if (context.frameName)
|
|
13835
13961
|
parts.push(context.frameName);
|
|
@@ -13873,7 +13999,7 @@ class ActionCoreService {
|
|
|
13873
13999
|
* @param context - Strategy execution context with strategyName, exchangeName and frameName
|
|
13874
14000
|
* @returns Promise that resolves when all validations complete
|
|
13875
14001
|
*/
|
|
13876
|
-
this.validate = memoize(([context]) => CREATE_KEY_FN$
|
|
14002
|
+
this.validate = memoize(([context]) => CREATE_KEY_FN$i(context), async (context) => {
|
|
13877
14003
|
this.loggerService.log(METHOD_NAME_VALIDATE, {
|
|
13878
14004
|
context,
|
|
13879
14005
|
});
|
|
@@ -18408,7 +18534,7 @@ const Markdown = new MarkdownAdapter();
|
|
|
18408
18534
|
* @param backtest - Whether running in backtest mode
|
|
18409
18535
|
* @returns Unique string key for memoization
|
|
18410
18536
|
*/
|
|
18411
|
-
const CREATE_KEY_FN$
|
|
18537
|
+
const CREATE_KEY_FN$h = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
18412
18538
|
const parts = [symbol, strategyName, exchangeName];
|
|
18413
18539
|
if (frameName)
|
|
18414
18540
|
parts.push(frameName);
|
|
@@ -18647,7 +18773,7 @@ class BacktestMarkdownService {
|
|
|
18647
18773
|
* Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
18648
18774
|
* Each combination gets its own isolated storage instance.
|
|
18649
18775
|
*/
|
|
18650
|
-
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
18776
|
+
this.getStorage = 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));
|
|
18651
18777
|
/**
|
|
18652
18778
|
* Processes tick events and accumulates closed signals.
|
|
18653
18779
|
* Should be called from IStrategyCallbacks.onTick.
|
|
@@ -18804,7 +18930,7 @@ class BacktestMarkdownService {
|
|
|
18804
18930
|
payload,
|
|
18805
18931
|
});
|
|
18806
18932
|
if (payload) {
|
|
18807
|
-
const key = CREATE_KEY_FN$
|
|
18933
|
+
const key = CREATE_KEY_FN$h(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
18808
18934
|
this.getStorage.clear(key);
|
|
18809
18935
|
}
|
|
18810
18936
|
else {
|
|
@@ -18866,7 +18992,7 @@ class BacktestMarkdownService {
|
|
|
18866
18992
|
* @param backtest - Whether running in backtest mode
|
|
18867
18993
|
* @returns Unique string key for memoization
|
|
18868
18994
|
*/
|
|
18869
|
-
const CREATE_KEY_FN$
|
|
18995
|
+
const CREATE_KEY_FN$g = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
18870
18996
|
const parts = [symbol, strategyName, exchangeName];
|
|
18871
18997
|
if (frameName)
|
|
18872
18998
|
parts.push(frameName);
|
|
@@ -19349,7 +19475,7 @@ class LiveMarkdownService {
|
|
|
19349
19475
|
* Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
19350
19476
|
* Each combination gets its own isolated storage instance.
|
|
19351
19477
|
*/
|
|
19352
|
-
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
19478
|
+
this.getStorage = 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));
|
|
19353
19479
|
/**
|
|
19354
19480
|
* Subscribes to live signal emitter to receive tick events.
|
|
19355
19481
|
* Protected against multiple subscriptions.
|
|
@@ -19567,7 +19693,7 @@ class LiveMarkdownService {
|
|
|
19567
19693
|
payload,
|
|
19568
19694
|
});
|
|
19569
19695
|
if (payload) {
|
|
19570
|
-
const key = CREATE_KEY_FN$
|
|
19696
|
+
const key = CREATE_KEY_FN$g(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
19571
19697
|
this.getStorage.clear(key);
|
|
19572
19698
|
}
|
|
19573
19699
|
else {
|
|
@@ -19587,7 +19713,7 @@ class LiveMarkdownService {
|
|
|
19587
19713
|
* @param backtest - Whether running in backtest mode
|
|
19588
19714
|
* @returns Unique string key for memoization
|
|
19589
19715
|
*/
|
|
19590
|
-
const CREATE_KEY_FN$
|
|
19716
|
+
const CREATE_KEY_FN$f = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
19591
19717
|
const parts = [symbol, strategyName, exchangeName];
|
|
19592
19718
|
if (frameName)
|
|
19593
19719
|
parts.push(frameName);
|
|
@@ -19878,7 +20004,7 @@ class ScheduleMarkdownService {
|
|
|
19878
20004
|
* Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
19879
20005
|
* Each combination gets its own isolated storage instance.
|
|
19880
20006
|
*/
|
|
19881
|
-
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
20007
|
+
this.getStorage = 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));
|
|
19882
20008
|
/**
|
|
19883
20009
|
* Subscribes to signal emitter to receive scheduled signal events.
|
|
19884
20010
|
* Protected against multiple subscriptions.
|
|
@@ -20081,7 +20207,7 @@ class ScheduleMarkdownService {
|
|
|
20081
20207
|
payload,
|
|
20082
20208
|
});
|
|
20083
20209
|
if (payload) {
|
|
20084
|
-
const key = CREATE_KEY_FN$
|
|
20210
|
+
const key = CREATE_KEY_FN$f(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
20085
20211
|
this.getStorage.clear(key);
|
|
20086
20212
|
}
|
|
20087
20213
|
else {
|
|
@@ -20101,7 +20227,7 @@ class ScheduleMarkdownService {
|
|
|
20101
20227
|
* @param backtest - Whether running in backtest mode
|
|
20102
20228
|
* @returns Unique string key for memoization
|
|
20103
20229
|
*/
|
|
20104
|
-
const CREATE_KEY_FN$
|
|
20230
|
+
const CREATE_KEY_FN$e = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
20105
20231
|
const parts = [symbol, strategyName, exchangeName];
|
|
20106
20232
|
if (frameName)
|
|
20107
20233
|
parts.push(frameName);
|
|
@@ -20349,7 +20475,7 @@ class PerformanceMarkdownService {
|
|
|
20349
20475
|
* Memoized function to get or create PerformanceStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
20350
20476
|
* Each combination gets its own isolated storage instance.
|
|
20351
20477
|
*/
|
|
20352
|
-
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
20478
|
+
this.getStorage = 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));
|
|
20353
20479
|
/**
|
|
20354
20480
|
* Subscribes to performance emitter to receive performance events.
|
|
20355
20481
|
* Protected against multiple subscriptions.
|
|
@@ -20516,7 +20642,7 @@ class PerformanceMarkdownService {
|
|
|
20516
20642
|
payload,
|
|
20517
20643
|
});
|
|
20518
20644
|
if (payload) {
|
|
20519
|
-
const key = CREATE_KEY_FN$
|
|
20645
|
+
const key = CREATE_KEY_FN$e(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
20520
20646
|
this.getStorage.clear(key);
|
|
20521
20647
|
}
|
|
20522
20648
|
else {
|
|
@@ -20986,7 +21112,7 @@ class WalkerMarkdownService {
|
|
|
20986
21112
|
* @param backtest - Whether running in backtest mode
|
|
20987
21113
|
* @returns Unique string key for memoization
|
|
20988
21114
|
*/
|
|
20989
|
-
const CREATE_KEY_FN$
|
|
21115
|
+
const CREATE_KEY_FN$d = (exchangeName, frameName, backtest) => {
|
|
20990
21116
|
const parts = [exchangeName];
|
|
20991
21117
|
if (frameName)
|
|
20992
21118
|
parts.push(frameName);
|
|
@@ -21353,7 +21479,7 @@ class HeatMarkdownService {
|
|
|
21353
21479
|
* Memoized function to get or create HeatmapStorage for exchange, frame and backtest mode.
|
|
21354
21480
|
* Each exchangeName + frameName + backtest mode combination gets its own isolated heatmap storage instance.
|
|
21355
21481
|
*/
|
|
21356
|
-
this.getStorage = memoize(([exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
21482
|
+
this.getStorage = memoize(([exchangeName, frameName, backtest]) => CREATE_KEY_FN$d(exchangeName, frameName, backtest), (exchangeName, frameName, backtest) => new HeatmapStorage(exchangeName, frameName, backtest));
|
|
21357
21483
|
/**
|
|
21358
21484
|
* Subscribes to signal emitter to receive tick events.
|
|
21359
21485
|
* Protected against multiple subscriptions.
|
|
@@ -21548,7 +21674,7 @@ class HeatMarkdownService {
|
|
|
21548
21674
|
payload,
|
|
21549
21675
|
});
|
|
21550
21676
|
if (payload) {
|
|
21551
|
-
const key = CREATE_KEY_FN$
|
|
21677
|
+
const key = CREATE_KEY_FN$d(payload.exchangeName, payload.frameName, payload.backtest);
|
|
21552
21678
|
this.getStorage.clear(key);
|
|
21553
21679
|
}
|
|
21554
21680
|
else {
|
|
@@ -22579,7 +22705,7 @@ class ClientPartial {
|
|
|
22579
22705
|
* @param backtest - Whether running in backtest mode
|
|
22580
22706
|
* @returns Unique string key for memoization
|
|
22581
22707
|
*/
|
|
22582
|
-
const CREATE_KEY_FN$
|
|
22708
|
+
const CREATE_KEY_FN$c = (signalId, backtest) => `${signalId}:${backtest ? "backtest" : "live"}`;
|
|
22583
22709
|
/**
|
|
22584
22710
|
* Creates a callback function for emitting profit events to partialProfitSubject.
|
|
22585
22711
|
*
|
|
@@ -22701,7 +22827,7 @@ class PartialConnectionService {
|
|
|
22701
22827
|
* Key format: "signalId:backtest" or "signalId:live"
|
|
22702
22828
|
* Value: ClientPartial instance with logger and event emitters
|
|
22703
22829
|
*/
|
|
22704
|
-
this.getPartial = memoize(([signalId, backtest]) => CREATE_KEY_FN$
|
|
22830
|
+
this.getPartial = memoize(([signalId, backtest]) => CREATE_KEY_FN$c(signalId, backtest), (signalId, backtest) => {
|
|
22705
22831
|
return new ClientPartial({
|
|
22706
22832
|
signalId,
|
|
22707
22833
|
logger: this.loggerService,
|
|
@@ -22791,7 +22917,7 @@ class PartialConnectionService {
|
|
|
22791
22917
|
const partial = this.getPartial(data.id, backtest);
|
|
22792
22918
|
await partial.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
|
|
22793
22919
|
await partial.clear(symbol, data, priceClose, backtest);
|
|
22794
|
-
const key = CREATE_KEY_FN$
|
|
22920
|
+
const key = CREATE_KEY_FN$c(data.id, backtest);
|
|
22795
22921
|
this.getPartial.clear(key);
|
|
22796
22922
|
};
|
|
22797
22923
|
}
|
|
@@ -22807,7 +22933,7 @@ class PartialConnectionService {
|
|
|
22807
22933
|
* @param backtest - Whether running in backtest mode
|
|
22808
22934
|
* @returns Unique string key for memoization
|
|
22809
22935
|
*/
|
|
22810
|
-
const CREATE_KEY_FN$
|
|
22936
|
+
const CREATE_KEY_FN$b = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
22811
22937
|
const parts = [symbol, strategyName, exchangeName];
|
|
22812
22938
|
if (frameName)
|
|
22813
22939
|
parts.push(frameName);
|
|
@@ -23032,7 +23158,7 @@ class PartialMarkdownService {
|
|
|
23032
23158
|
* Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
23033
23159
|
* Each combination gets its own isolated storage instance.
|
|
23034
23160
|
*/
|
|
23035
|
-
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
23161
|
+
this.getStorage = 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));
|
|
23036
23162
|
/**
|
|
23037
23163
|
* Subscribes to partial profit/loss signal emitters to receive events.
|
|
23038
23164
|
* Protected against multiple subscriptions.
|
|
@@ -23242,7 +23368,7 @@ class PartialMarkdownService {
|
|
|
23242
23368
|
payload,
|
|
23243
23369
|
});
|
|
23244
23370
|
if (payload) {
|
|
23245
|
-
const key = CREATE_KEY_FN$
|
|
23371
|
+
const key = CREATE_KEY_FN$b(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
23246
23372
|
this.getStorage.clear(key);
|
|
23247
23373
|
}
|
|
23248
23374
|
else {
|
|
@@ -23258,7 +23384,7 @@ class PartialMarkdownService {
|
|
|
23258
23384
|
* @param context - Context with strategyName, exchangeName, frameName
|
|
23259
23385
|
* @returns Unique string key for memoization
|
|
23260
23386
|
*/
|
|
23261
|
-
const CREATE_KEY_FN$
|
|
23387
|
+
const CREATE_KEY_FN$a = (context) => {
|
|
23262
23388
|
const parts = [context.strategyName, context.exchangeName];
|
|
23263
23389
|
if (context.frameName)
|
|
23264
23390
|
parts.push(context.frameName);
|
|
@@ -23332,7 +23458,7 @@ class PartialGlobalService {
|
|
|
23332
23458
|
* @param context - Context with strategyName, exchangeName and frameName
|
|
23333
23459
|
* @param methodName - Name of the calling method for error tracking
|
|
23334
23460
|
*/
|
|
23335
|
-
this.validate = memoize(([context]) => CREATE_KEY_FN$
|
|
23461
|
+
this.validate = memoize(([context]) => CREATE_KEY_FN$a(context), (context, methodName) => {
|
|
23336
23462
|
this.loggerService.log("partialGlobalService validate", {
|
|
23337
23463
|
context,
|
|
23338
23464
|
methodName,
|
|
@@ -23787,7 +23913,7 @@ class ClientBreakeven {
|
|
|
23787
23913
|
* @param backtest - Whether running in backtest mode
|
|
23788
23914
|
* @returns Unique string key for memoization
|
|
23789
23915
|
*/
|
|
23790
|
-
const CREATE_KEY_FN$
|
|
23916
|
+
const CREATE_KEY_FN$9 = (signalId, backtest) => `${signalId}:${backtest ? "backtest" : "live"}`;
|
|
23791
23917
|
/**
|
|
23792
23918
|
* Creates a callback function for emitting breakeven events to breakevenSubject.
|
|
23793
23919
|
*
|
|
@@ -23873,7 +23999,7 @@ class BreakevenConnectionService {
|
|
|
23873
23999
|
* Key format: "signalId:backtest" or "signalId:live"
|
|
23874
24000
|
* Value: ClientBreakeven instance with logger and event emitter
|
|
23875
24001
|
*/
|
|
23876
|
-
this.getBreakeven = memoize(([signalId, backtest]) => CREATE_KEY_FN$
|
|
24002
|
+
this.getBreakeven = memoize(([signalId, backtest]) => CREATE_KEY_FN$9(signalId, backtest), (signalId, backtest) => {
|
|
23877
24003
|
return new ClientBreakeven({
|
|
23878
24004
|
signalId,
|
|
23879
24005
|
logger: this.loggerService,
|
|
@@ -23934,7 +24060,7 @@ class BreakevenConnectionService {
|
|
|
23934
24060
|
const breakeven = this.getBreakeven(data.id, backtest);
|
|
23935
24061
|
await breakeven.waitForInit(symbol, data.strategyName, data.exchangeName, backtest);
|
|
23936
24062
|
await breakeven.clear(symbol, data, priceClose, backtest);
|
|
23937
|
-
const key = CREATE_KEY_FN$
|
|
24063
|
+
const key = CREATE_KEY_FN$9(data.id, backtest);
|
|
23938
24064
|
this.getBreakeven.clear(key);
|
|
23939
24065
|
};
|
|
23940
24066
|
}
|
|
@@ -23950,7 +24076,7 @@ class BreakevenConnectionService {
|
|
|
23950
24076
|
* @param backtest - Whether running in backtest mode
|
|
23951
24077
|
* @returns Unique string key for memoization
|
|
23952
24078
|
*/
|
|
23953
|
-
const CREATE_KEY_FN$
|
|
24079
|
+
const CREATE_KEY_FN$8 = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
23954
24080
|
const parts = [symbol, strategyName, exchangeName];
|
|
23955
24081
|
if (frameName)
|
|
23956
24082
|
parts.push(frameName);
|
|
@@ -24127,7 +24253,7 @@ class BreakevenMarkdownService {
|
|
|
24127
24253
|
* Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
24128
24254
|
* Each combination gets its own isolated storage instance.
|
|
24129
24255
|
*/
|
|
24130
|
-
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
24256
|
+
this.getStorage = 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));
|
|
24131
24257
|
/**
|
|
24132
24258
|
* Subscribes to breakeven signal emitter to receive events.
|
|
24133
24259
|
* Protected against multiple subscriptions.
|
|
@@ -24316,7 +24442,7 @@ class BreakevenMarkdownService {
|
|
|
24316
24442
|
payload,
|
|
24317
24443
|
});
|
|
24318
24444
|
if (payload) {
|
|
24319
|
-
const key = CREATE_KEY_FN$
|
|
24445
|
+
const key = CREATE_KEY_FN$8(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
24320
24446
|
this.getStorage.clear(key);
|
|
24321
24447
|
}
|
|
24322
24448
|
else {
|
|
@@ -24332,7 +24458,7 @@ class BreakevenMarkdownService {
|
|
|
24332
24458
|
* @param context - Context with strategyName, exchangeName, frameName
|
|
24333
24459
|
* @returns Unique string key for memoization
|
|
24334
24460
|
*/
|
|
24335
|
-
const CREATE_KEY_FN$
|
|
24461
|
+
const CREATE_KEY_FN$7 = (context) => {
|
|
24336
24462
|
const parts = [context.strategyName, context.exchangeName];
|
|
24337
24463
|
if (context.frameName)
|
|
24338
24464
|
parts.push(context.frameName);
|
|
@@ -24406,7 +24532,7 @@ class BreakevenGlobalService {
|
|
|
24406
24532
|
* @param context - Context with strategyName, exchangeName and frameName
|
|
24407
24533
|
* @param methodName - Name of the calling method for error tracking
|
|
24408
24534
|
*/
|
|
24409
|
-
this.validate = memoize(([context]) => CREATE_KEY_FN$
|
|
24535
|
+
this.validate = memoize(([context]) => CREATE_KEY_FN$7(context), (context, methodName) => {
|
|
24410
24536
|
this.loggerService.log("breakevenGlobalService validate", {
|
|
24411
24537
|
context,
|
|
24412
24538
|
methodName,
|
|
@@ -24626,7 +24752,7 @@ class ConfigValidationService {
|
|
|
24626
24752
|
* @param backtest - Whether running in backtest mode
|
|
24627
24753
|
* @returns Unique string key for memoization
|
|
24628
24754
|
*/
|
|
24629
|
-
const CREATE_KEY_FN$
|
|
24755
|
+
const CREATE_KEY_FN$6 = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
24630
24756
|
const parts = [symbol, strategyName, exchangeName];
|
|
24631
24757
|
if (frameName)
|
|
24632
24758
|
parts.push(frameName);
|
|
@@ -24795,7 +24921,7 @@ class RiskMarkdownService {
|
|
|
24795
24921
|
* Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
|
|
24796
24922
|
* Each combination gets its own isolated storage instance.
|
|
24797
24923
|
*/
|
|
24798
|
-
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
24924
|
+
this.getStorage = 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));
|
|
24799
24925
|
/**
|
|
24800
24926
|
* Subscribes to risk rejection emitter to receive rejection events.
|
|
24801
24927
|
* Protected against multiple subscriptions.
|
|
@@ -24984,7 +25110,7 @@ class RiskMarkdownService {
|
|
|
24984
25110
|
payload,
|
|
24985
25111
|
});
|
|
24986
25112
|
if (payload) {
|
|
24987
|
-
const key = CREATE_KEY_FN$
|
|
25113
|
+
const key = CREATE_KEY_FN$6(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
24988
25114
|
this.getStorage.clear(key);
|
|
24989
25115
|
}
|
|
24990
25116
|
else {
|
|
@@ -27672,7 +27798,7 @@ class SyncReportService {
|
|
|
27672
27798
|
* @returns Colon-separated key string for memoization
|
|
27673
27799
|
* @internal
|
|
27674
27800
|
*/
|
|
27675
|
-
const CREATE_KEY_FN$
|
|
27801
|
+
const CREATE_KEY_FN$5 = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
27676
27802
|
const parts = [symbol, strategyName, exchangeName];
|
|
27677
27803
|
if (frameName)
|
|
27678
27804
|
parts.push(frameName);
|
|
@@ -27920,7 +28046,7 @@ class StrategyMarkdownService {
|
|
|
27920
28046
|
*
|
|
27921
28047
|
* @internal
|
|
27922
28048
|
*/
|
|
27923
|
-
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
28049
|
+
this.getStorage = 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));
|
|
27924
28050
|
/**
|
|
27925
28051
|
* Records a cancel-scheduled event when a scheduled signal is cancelled.
|
|
27926
28052
|
*
|
|
@@ -28488,7 +28614,7 @@ class StrategyMarkdownService {
|
|
|
28488
28614
|
this.clear = async (payload) => {
|
|
28489
28615
|
this.loggerService.log("strategyMarkdownService clear", { payload });
|
|
28490
28616
|
if (payload) {
|
|
28491
|
-
const key = CREATE_KEY_FN$
|
|
28617
|
+
const key = CREATE_KEY_FN$5(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
28492
28618
|
this.getStorage.clear(key);
|
|
28493
28619
|
}
|
|
28494
28620
|
else {
|
|
@@ -28596,7 +28722,7 @@ class StrategyMarkdownService {
|
|
|
28596
28722
|
* Creates a unique key for memoizing ReportStorage instances.
|
|
28597
28723
|
* Key format: "symbol:strategyName:exchangeName[:frameName]:backtest|live"
|
|
28598
28724
|
*/
|
|
28599
|
-
const CREATE_KEY_FN$
|
|
28725
|
+
const CREATE_KEY_FN$4 = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
28600
28726
|
const parts = [symbol, strategyName, exchangeName];
|
|
28601
28727
|
if (frameName)
|
|
28602
28728
|
parts.push(frameName);
|
|
@@ -28728,7 +28854,7 @@ class ReportStorage {
|
|
|
28728
28854
|
class SyncMarkdownService {
|
|
28729
28855
|
constructor() {
|
|
28730
28856
|
this.loggerService = inject(TYPES.loggerService);
|
|
28731
|
-
this.getStorage = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$
|
|
28857
|
+
this.getStorage = 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));
|
|
28732
28858
|
this.subscribe = singleshot(() => {
|
|
28733
28859
|
this.loggerService.log("syncMarkdownService init");
|
|
28734
28860
|
const unsubscribe = syncSubject.subscribe(this.tick);
|
|
@@ -28803,7 +28929,7 @@ class SyncMarkdownService {
|
|
|
28803
28929
|
this.clear = async (payload) => {
|
|
28804
28930
|
this.loggerService.log("syncMarkdownService clear", { payload });
|
|
28805
28931
|
if (payload) {
|
|
28806
|
-
const key = CREATE_KEY_FN$
|
|
28932
|
+
const key = CREATE_KEY_FN$4(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
28807
28933
|
this.getStorage.clear(key);
|
|
28808
28934
|
}
|
|
28809
28935
|
else {
|
|
@@ -28813,6 +28939,275 @@ class SyncMarkdownService {
|
|
|
28813
28939
|
}
|
|
28814
28940
|
}
|
|
28815
28941
|
|
|
28942
|
+
const LISTEN_TIMEOUT$1 = 120000;
|
|
28943
|
+
/**
|
|
28944
|
+
* Creates a unique memoization key for a price stream.
|
|
28945
|
+
* Key format: "symbol:strategyName:exchangeName[:frameName]:backtest|live"
|
|
28946
|
+
*
|
|
28947
|
+
* @param symbol - Trading pair symbol (e.g., "BTCUSDT")
|
|
28948
|
+
* @param strategyName - Strategy identifier
|
|
28949
|
+
* @param exchangeName - Exchange identifier
|
|
28950
|
+
* @param frameName - Frame identifier (omitted when empty)
|
|
28951
|
+
* @param backtest - Whether running in backtest mode
|
|
28952
|
+
* @returns Unique string key for memoization
|
|
28953
|
+
*/
|
|
28954
|
+
const CREATE_KEY_FN$3 = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
28955
|
+
const parts = [symbol, strategyName, exchangeName];
|
|
28956
|
+
if (frameName)
|
|
28957
|
+
parts.push(frameName);
|
|
28958
|
+
parts.push(backtest ? "backtest" : "live");
|
|
28959
|
+
return parts.join(":");
|
|
28960
|
+
};
|
|
28961
|
+
/**
|
|
28962
|
+
* Service for tracking the latest market price per symbol-strategy-exchange-frame combination.
|
|
28963
|
+
*
|
|
28964
|
+
* Maintains a memoized BehaviorSubject per unique key that is updated on every strategy tick
|
|
28965
|
+
* by StrategyConnectionService. Consumers can synchronously read the last known price or
|
|
28966
|
+
* await the first value if none has arrived yet.
|
|
28967
|
+
*
|
|
28968
|
+
* Primary use case: providing the current price outside of a tick execution context,
|
|
28969
|
+
* e.g., when a command is triggered between ticks.
|
|
28970
|
+
*
|
|
28971
|
+
* Features:
|
|
28972
|
+
* - One BehaviorSubject per (symbol, strategyName, exchangeName, frameName, backtest) key
|
|
28973
|
+
* - Falls back to ExchangeConnectionService.getAveragePrice when called inside an execution context
|
|
28974
|
+
* - Waits up to LISTEN_TIMEOUT ms for the first price if none is cached yet
|
|
28975
|
+
* - clear() disposes the BehaviorSubject for a single key or all keys
|
|
28976
|
+
*
|
|
28977
|
+
* Architecture:
|
|
28978
|
+
* - Registered as singleton in DI container
|
|
28979
|
+
* - Updated by StrategyConnectionService after each tick
|
|
28980
|
+
* - Cleared by Backtest/Live/Walker at strategy start to prevent stale data
|
|
28981
|
+
*
|
|
28982
|
+
* @example
|
|
28983
|
+
* ```typescript
|
|
28984
|
+
* const price = await backtest.priceMetaService.getCurrentPrice("BTCUSDT", context, false);
|
|
28985
|
+
* ```
|
|
28986
|
+
*/
|
|
28987
|
+
class PriceMetaService {
|
|
28988
|
+
constructor() {
|
|
28989
|
+
this.loggerService = inject(TYPES.loggerService);
|
|
28990
|
+
this.exchangeConnectionService = inject(TYPES.exchangeConnectionService);
|
|
28991
|
+
/**
|
|
28992
|
+
* Memoized factory for BehaviorSubject streams keyed by (symbol, strategyName, exchangeName, frameName, backtest).
|
|
28993
|
+
*
|
|
28994
|
+
* Each subject holds the latest currentPrice emitted by the strategy iterator for that key.
|
|
28995
|
+
* Instances are cached until clear() is called.
|
|
28996
|
+
*/
|
|
28997
|
+
this.getSource = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$3(symbol, strategyName, exchangeName, frameName, backtest), () => new BehaviorSubject());
|
|
28998
|
+
/**
|
|
28999
|
+
* Returns the current market price for the given symbol and context.
|
|
29000
|
+
*
|
|
29001
|
+
* When called inside an execution context (i.e., during a signal handler or action),
|
|
29002
|
+
* delegates to ExchangeConnectionService.getAveragePrice for the live exchange price.
|
|
29003
|
+
* Otherwise, reads the last value from the cached BehaviorSubject. If no value has
|
|
29004
|
+
* been emitted yet, waits up to LISTEN_TIMEOUT ms for the first tick before throwing.
|
|
29005
|
+
*
|
|
29006
|
+
* @param symbol - Trading pair symbol (e.g., "BTCUSDT")
|
|
29007
|
+
* @param context - Strategy, exchange, and frame identifiers
|
|
29008
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
29009
|
+
* @returns Current market price in quote currency
|
|
29010
|
+
* @throws When no price arrives within LISTEN_TIMEOUT ms
|
|
29011
|
+
*/
|
|
29012
|
+
this.getCurrentPrice = async (symbol, context, backtest) => {
|
|
29013
|
+
this.loggerService.log("priceMetaService getCurrentPrice", {
|
|
29014
|
+
symbol,
|
|
29015
|
+
context,
|
|
29016
|
+
backtest,
|
|
29017
|
+
});
|
|
29018
|
+
if (ExecutionContextService.hasContext() &&
|
|
29019
|
+
MethodContextService.hasContext()) {
|
|
29020
|
+
return await this.exchangeConnectionService.getAveragePrice(symbol);
|
|
29021
|
+
}
|
|
29022
|
+
const source = this.getSource(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
29023
|
+
if (source.data) {
|
|
29024
|
+
return source.data;
|
|
29025
|
+
}
|
|
29026
|
+
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...`);
|
|
29027
|
+
const currentPrice = await waitForNext(source, (data) => !!data, LISTEN_TIMEOUT$1);
|
|
29028
|
+
if (typeof currentPrice === "symbol") {
|
|
29029
|
+
throw new Error(`PriceMetaService: Timeout while waiting for currentPrice for ${CREATE_KEY_FN$3(symbol, context.strategyName, context.exchangeName, context.frameName, backtest)}`);
|
|
29030
|
+
}
|
|
29031
|
+
return currentPrice;
|
|
29032
|
+
};
|
|
29033
|
+
/**
|
|
29034
|
+
* Pushes a new price value into the BehaviorSubject for the given key.
|
|
29035
|
+
*
|
|
29036
|
+
* Called by StrategyConnectionService after each strategy tick to keep
|
|
29037
|
+
* the cached price up to date.
|
|
29038
|
+
*
|
|
29039
|
+
* @param symbol - Trading pair symbol (e.g., "BTCUSDT")
|
|
29040
|
+
* @param currentPrice - The latest price from the tick
|
|
29041
|
+
* @param context - Strategy, exchange, and frame identifiers
|
|
29042
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
29043
|
+
*/
|
|
29044
|
+
this.next = async (symbol, currentPrice, context, backtest) => {
|
|
29045
|
+
this.loggerService.log("priceMetaService next", {
|
|
29046
|
+
symbol,
|
|
29047
|
+
currentPrice,
|
|
29048
|
+
context,
|
|
29049
|
+
backtest,
|
|
29050
|
+
});
|
|
29051
|
+
const source = this.getSource(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
29052
|
+
source.next(currentPrice);
|
|
29053
|
+
};
|
|
29054
|
+
/**
|
|
29055
|
+
* Disposes cached BehaviorSubject(s) to free memory and prevent stale data.
|
|
29056
|
+
*
|
|
29057
|
+
* When called without arguments, clears all memoized price streams.
|
|
29058
|
+
* When called with a payload, clears only the stream for the specified key.
|
|
29059
|
+
* Should be called at strategy start (Backtest/Live/Walker) to reset state.
|
|
29060
|
+
*
|
|
29061
|
+
* @param payload - Optional key to clear a single stream; omit to clear all
|
|
29062
|
+
*/
|
|
29063
|
+
this.clear = (payload) => {
|
|
29064
|
+
this.loggerService.log("priceMetaService clear", {
|
|
29065
|
+
payload
|
|
29066
|
+
});
|
|
29067
|
+
if (!payload) {
|
|
29068
|
+
this.getSource.clear();
|
|
29069
|
+
return;
|
|
29070
|
+
}
|
|
29071
|
+
const key = CREATE_KEY_FN$3(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
29072
|
+
this.getSource.clear(key);
|
|
29073
|
+
};
|
|
29074
|
+
}
|
|
29075
|
+
}
|
|
29076
|
+
|
|
29077
|
+
const LISTEN_TIMEOUT = 120000;
|
|
29078
|
+
/**
|
|
29079
|
+
* Creates a unique memoization key for a timestamp stream.
|
|
29080
|
+
* Key format: "symbol:strategyName:exchangeName[:frameName]:backtest|live"
|
|
29081
|
+
*
|
|
29082
|
+
* @param symbol - Trading pair symbol (e.g., "BTCUSDT")
|
|
29083
|
+
* @param strategyName - Strategy identifier
|
|
29084
|
+
* @param exchangeName - Exchange identifier
|
|
29085
|
+
* @param frameName - Frame identifier (omitted when empty)
|
|
29086
|
+
* @param backtest - Whether running in backtest mode
|
|
29087
|
+
* @returns Unique string key for memoization
|
|
29088
|
+
*/
|
|
29089
|
+
const CREATE_KEY_FN$2 = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
29090
|
+
const parts = [symbol, strategyName, exchangeName];
|
|
29091
|
+
if (frameName)
|
|
29092
|
+
parts.push(frameName);
|
|
29093
|
+
parts.push(backtest ? "backtest" : "live");
|
|
29094
|
+
return parts.join(":");
|
|
29095
|
+
};
|
|
29096
|
+
/**
|
|
29097
|
+
* Service for tracking the latest candle timestamp per symbol-strategy-exchange-frame combination.
|
|
29098
|
+
*
|
|
29099
|
+
* Maintains a memoized BehaviorSubject per unique key that is updated on every strategy tick
|
|
29100
|
+
* by StrategyConnectionService. Consumers can synchronously read the last known timestamp or
|
|
29101
|
+
* await the first value if none has arrived yet.
|
|
29102
|
+
*
|
|
29103
|
+
* Primary use case: providing the current candle time outside of a tick execution context,
|
|
29104
|
+
* e.g., when a command is triggered between ticks.
|
|
29105
|
+
*
|
|
29106
|
+
* Features:
|
|
29107
|
+
* - One BehaviorSubject per (symbol, strategyName, exchangeName, frameName, backtest) key
|
|
29108
|
+
* - Falls back to ExecutionContextService.context.when when called inside an execution context
|
|
29109
|
+
* - Waits up to LISTEN_TIMEOUT ms for the first timestamp if none is cached yet
|
|
29110
|
+
* - clear() disposes the BehaviorSubject for a single key or all keys
|
|
29111
|
+
*
|
|
29112
|
+
* Architecture:
|
|
29113
|
+
* - Registered as singleton in DI container
|
|
29114
|
+
* - Updated by StrategyConnectionService after each tick
|
|
29115
|
+
* - Cleared by Backtest/Live/Walker at strategy start to prevent stale data
|
|
29116
|
+
*
|
|
29117
|
+
* @example
|
|
29118
|
+
* ```typescript
|
|
29119
|
+
* const ts = await backtest.timeMetaService.getTimestamp("BTCUSDT", context, false);
|
|
29120
|
+
* ```
|
|
29121
|
+
*/
|
|
29122
|
+
class TimeMetaService {
|
|
29123
|
+
constructor() {
|
|
29124
|
+
this.loggerService = inject(TYPES.loggerService);
|
|
29125
|
+
this.executionContextService = inject(TYPES.executionContextService);
|
|
29126
|
+
/**
|
|
29127
|
+
* Memoized factory for BehaviorSubject streams keyed by (symbol, strategyName, exchangeName, frameName, backtest).
|
|
29128
|
+
*
|
|
29129
|
+
* Each subject holds the latest createdAt timestamp emitted by the strategy iterator for that key.
|
|
29130
|
+
* Instances are cached until clear() is called.
|
|
29131
|
+
*/
|
|
29132
|
+
this.getSource = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN$2(symbol, strategyName, exchangeName, frameName, backtest), () => new BehaviorSubject());
|
|
29133
|
+
/**
|
|
29134
|
+
* Returns the current candle timestamp (in milliseconds) for the given symbol and context.
|
|
29135
|
+
*
|
|
29136
|
+
* When called inside an execution context (i.e., during a signal handler or action),
|
|
29137
|
+
* reads the timestamp directly from ExecutionContextService.context.when.
|
|
29138
|
+
* Otherwise, reads the last value from the cached BehaviorSubject. If no value has
|
|
29139
|
+
* been emitted yet, waits up to LISTEN_TIMEOUT ms for the first tick before throwing.
|
|
29140
|
+
*
|
|
29141
|
+
* @param symbol - Trading pair symbol (e.g., "BTCUSDT")
|
|
29142
|
+
* @param context - Strategy, exchange, and frame identifiers
|
|
29143
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
29144
|
+
* @returns Unix timestamp in milliseconds of the latest processed candle
|
|
29145
|
+
* @throws When no timestamp arrives within LISTEN_TIMEOUT ms
|
|
29146
|
+
*/
|
|
29147
|
+
this.getTimestamp = async (symbol, context, backtest) => {
|
|
29148
|
+
this.loggerService.log("timeMetaService getTimestamp", {
|
|
29149
|
+
symbol,
|
|
29150
|
+
context,
|
|
29151
|
+
backtest,
|
|
29152
|
+
});
|
|
29153
|
+
if (ExecutionContextService.hasContext()) {
|
|
29154
|
+
return this.executionContextService.context.when.getTime();
|
|
29155
|
+
}
|
|
29156
|
+
const source = this.getSource(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
29157
|
+
if (source.data) {
|
|
29158
|
+
return source.data;
|
|
29159
|
+
}
|
|
29160
|
+
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...`);
|
|
29161
|
+
const timestamp = await waitForNext(source, (data) => !!data, LISTEN_TIMEOUT);
|
|
29162
|
+
if (typeof timestamp === "symbol") {
|
|
29163
|
+
throw new Error(`TimeMetaService: Timeout while waiting for timestamp for ${CREATE_KEY_FN$2(symbol, context.strategyName, context.exchangeName, context.frameName, backtest)}`);
|
|
29164
|
+
}
|
|
29165
|
+
return timestamp;
|
|
29166
|
+
};
|
|
29167
|
+
/**
|
|
29168
|
+
* Pushes a new timestamp value into the BehaviorSubject for the given key.
|
|
29169
|
+
*
|
|
29170
|
+
* Called by StrategyConnectionService after each strategy tick to keep
|
|
29171
|
+
* the cached timestamp up to date.
|
|
29172
|
+
*
|
|
29173
|
+
* @param symbol - Trading pair symbol (e.g., "BTCUSDT")
|
|
29174
|
+
* @param timestamp - The createdAt timestamp from the tick (milliseconds)
|
|
29175
|
+
* @param context - Strategy, exchange, and frame identifiers
|
|
29176
|
+
* @param backtest - True if backtest mode, false if live mode
|
|
29177
|
+
*/
|
|
29178
|
+
this.next = async (symbol, timestamp, context, backtest) => {
|
|
29179
|
+
this.loggerService.log("timeMetaService next", {
|
|
29180
|
+
symbol,
|
|
29181
|
+
timestamp,
|
|
29182
|
+
context,
|
|
29183
|
+
backtest,
|
|
29184
|
+
});
|
|
29185
|
+
const source = this.getSource(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
29186
|
+
source.next(timestamp);
|
|
29187
|
+
};
|
|
29188
|
+
/**
|
|
29189
|
+
* Disposes cached BehaviorSubject(s) to free memory and prevent stale data.
|
|
29190
|
+
*
|
|
29191
|
+
* When called without arguments, clears all memoized timestamp streams.
|
|
29192
|
+
* When called with a payload, clears only the stream for the specified key.
|
|
29193
|
+
* Should be called at strategy start (Backtest/Live/Walker) to reset state.
|
|
29194
|
+
*
|
|
29195
|
+
* @param payload - Optional key to clear a single stream; omit to clear all
|
|
29196
|
+
*/
|
|
29197
|
+
this.clear = (payload) => {
|
|
29198
|
+
this.loggerService.log("timeMetaService clear", {
|
|
29199
|
+
payload,
|
|
29200
|
+
});
|
|
29201
|
+
if (!payload) {
|
|
29202
|
+
this.getSource.clear();
|
|
29203
|
+
return;
|
|
29204
|
+
}
|
|
29205
|
+
const key = CREATE_KEY_FN$2(payload.symbol, payload.strategyName, payload.exchangeName, payload.frameName, payload.backtest);
|
|
29206
|
+
this.getSource.clear(key);
|
|
29207
|
+
};
|
|
29208
|
+
}
|
|
29209
|
+
}
|
|
29210
|
+
|
|
28816
29211
|
{
|
|
28817
29212
|
provide(TYPES.loggerService, () => new LoggerService());
|
|
28818
29213
|
}
|
|
@@ -28845,6 +29240,10 @@ class SyncMarkdownService {
|
|
|
28845
29240
|
provide(TYPES.actionCoreService, () => new ActionCoreService());
|
|
28846
29241
|
provide(TYPES.frameCoreService, () => new FrameCoreService());
|
|
28847
29242
|
}
|
|
29243
|
+
{
|
|
29244
|
+
provide(TYPES.priceMetaService, () => new PriceMetaService());
|
|
29245
|
+
provide(TYPES.timeMetaService, () => new TimeMetaService());
|
|
29246
|
+
}
|
|
28848
29247
|
{
|
|
28849
29248
|
provide(TYPES.sizingGlobalService, () => new SizingGlobalService());
|
|
28850
29249
|
provide(TYPES.riskGlobalService, () => new RiskGlobalService());
|
|
@@ -28936,6 +29335,10 @@ const coreServices = {
|
|
|
28936
29335
|
actionCoreService: inject(TYPES.actionCoreService),
|
|
28937
29336
|
frameCoreService: inject(TYPES.frameCoreService),
|
|
28938
29337
|
};
|
|
29338
|
+
const metaServices = {
|
|
29339
|
+
timeMetaService: inject(TYPES.timeMetaService),
|
|
29340
|
+
priceMetaService: inject(TYPES.priceMetaService),
|
|
29341
|
+
};
|
|
28939
29342
|
const globalServices = {
|
|
28940
29343
|
sizingGlobalService: inject(TYPES.sizingGlobalService),
|
|
28941
29344
|
riskGlobalService: inject(TYPES.riskGlobalService),
|
|
@@ -29000,6 +29403,7 @@ const backtest = {
|
|
|
29000
29403
|
...connectionServices,
|
|
29001
29404
|
...schemaServices,
|
|
29002
29405
|
...coreServices,
|
|
29406
|
+
...metaServices,
|
|
29003
29407
|
...globalServices,
|
|
29004
29408
|
...commandServices,
|
|
29005
29409
|
...logicPrivateServices,
|
|
@@ -34486,6 +34890,20 @@ class BacktestInstance {
|
|
|
34486
34890
|
frameName: context.frameName,
|
|
34487
34891
|
backtest: true,
|
|
34488
34892
|
});
|
|
34893
|
+
bt.timeMetaService.clear({
|
|
34894
|
+
symbol,
|
|
34895
|
+
strategyName: context.strategyName,
|
|
34896
|
+
exchangeName: context.exchangeName,
|
|
34897
|
+
frameName: context.frameName,
|
|
34898
|
+
backtest: true,
|
|
34899
|
+
});
|
|
34900
|
+
bt.priceMetaService.clear({
|
|
34901
|
+
symbol,
|
|
34902
|
+
strategyName: context.strategyName,
|
|
34903
|
+
exchangeName: context.exchangeName,
|
|
34904
|
+
frameName: context.frameName,
|
|
34905
|
+
backtest: true,
|
|
34906
|
+
});
|
|
34489
34907
|
}
|
|
34490
34908
|
{
|
|
34491
34909
|
const { riskName, riskList, actions } = bt.strategySchemaService.get(context.strategyName);
|
|
@@ -36390,6 +36808,20 @@ class LiveInstance {
|
|
|
36390
36808
|
frameName: "",
|
|
36391
36809
|
backtest: false,
|
|
36392
36810
|
});
|
|
36811
|
+
bt.timeMetaService.clear({
|
|
36812
|
+
symbol,
|
|
36813
|
+
strategyName: context.strategyName,
|
|
36814
|
+
exchangeName: context.exchangeName,
|
|
36815
|
+
frameName: "",
|
|
36816
|
+
backtest: false,
|
|
36817
|
+
});
|
|
36818
|
+
bt.priceMetaService.clear({
|
|
36819
|
+
symbol,
|
|
36820
|
+
strategyName: context.strategyName,
|
|
36821
|
+
exchangeName: context.exchangeName,
|
|
36822
|
+
frameName: "",
|
|
36823
|
+
backtest: false,
|
|
36824
|
+
});
|
|
36393
36825
|
}
|
|
36394
36826
|
{
|
|
36395
36827
|
const { riskName, riskList, actions } = bt.strategySchemaService.get(context.strategyName);
|
|
@@ -40538,6 +40970,20 @@ class WalkerInstance {
|
|
|
40538
40970
|
frameName: walkerSchema.frameName,
|
|
40539
40971
|
backtest: true,
|
|
40540
40972
|
});
|
|
40973
|
+
bt.timeMetaService.clear({
|
|
40974
|
+
symbol,
|
|
40975
|
+
strategyName,
|
|
40976
|
+
exchangeName: walkerSchema.exchangeName,
|
|
40977
|
+
frameName: walkerSchema.frameName,
|
|
40978
|
+
backtest: true,
|
|
40979
|
+
});
|
|
40980
|
+
bt.priceMetaService.clear({
|
|
40981
|
+
symbol,
|
|
40982
|
+
strategyName,
|
|
40983
|
+
exchangeName: walkerSchema.exchangeName,
|
|
40984
|
+
frameName: walkerSchema.frameName,
|
|
40985
|
+
backtest: true,
|
|
40986
|
+
});
|
|
40541
40987
|
}
|
|
40542
40988
|
{
|
|
40543
40989
|
const { riskName, riskList, actions } = bt.strategySchemaService.get(strategyName);
|
|
@@ -43505,13 +43951,15 @@ class NotificationMemoryBacktestUtils {
|
|
|
43505
43951
|
* Handles signal sync events (signal-open, signal-close).
|
|
43506
43952
|
* @param data - The signal sync contract data
|
|
43507
43953
|
*/
|
|
43508
|
-
this.handleSync = async (data) => {
|
|
43954
|
+
this.handleSync = trycatch(async (data) => {
|
|
43509
43955
|
bt.loggerService.info(NOTIFICATION_MEMORY_BACKTEST_METHOD_NAME_HANDLE_SYNC, {
|
|
43510
43956
|
signalId: data.signalId,
|
|
43511
43957
|
action: data.action,
|
|
43512
43958
|
});
|
|
43513
43959
|
this._addNotification(CREATE_SIGNAL_SYNC_NOTIFICATION_FN(data));
|
|
43514
|
-
}
|
|
43960
|
+
}, {
|
|
43961
|
+
defaultValue: null,
|
|
43962
|
+
});
|
|
43515
43963
|
/**
|
|
43516
43964
|
* Handles risk rejection event.
|
|
43517
43965
|
* @param data - The risk contract data
|
|
@@ -43620,8 +44068,10 @@ class NotificationDummyBacktestUtils {
|
|
|
43620
44068
|
/**
|
|
43621
44069
|
* No-op handler for signal sync event.
|
|
43622
44070
|
*/
|
|
43623
|
-
this.handleSync = async () => {
|
|
43624
|
-
}
|
|
44071
|
+
this.handleSync = trycatch(async () => {
|
|
44072
|
+
}, {
|
|
44073
|
+
defaultValue: null,
|
|
44074
|
+
});
|
|
43625
44075
|
/**
|
|
43626
44076
|
* No-op handler for risk rejection event.
|
|
43627
44077
|
*/
|
|
@@ -43760,7 +44210,7 @@ class NotificationPersistBacktestUtils {
|
|
|
43760
44210
|
* Handles signal sync events (signal-open, signal-close).
|
|
43761
44211
|
* @param data - The signal sync contract data
|
|
43762
44212
|
*/
|
|
43763
|
-
this.handleSync = async (data) => {
|
|
44213
|
+
this.handleSync = trycatch(async (data) => {
|
|
43764
44214
|
bt.loggerService.info(NOTIFICATION_PERSIST_BACKTEST_METHOD_NAME_HANDLE_SYNC, {
|
|
43765
44215
|
signalId: data.signalId,
|
|
43766
44216
|
action: data.action,
|
|
@@ -43768,7 +44218,9 @@ class NotificationPersistBacktestUtils {
|
|
|
43768
44218
|
await this.waitForInit();
|
|
43769
44219
|
this._addNotification(CREATE_SIGNAL_SYNC_NOTIFICATION_FN(data));
|
|
43770
44220
|
await this._updateNotifications();
|
|
43771
|
-
}
|
|
44221
|
+
}, {
|
|
44222
|
+
defaultValue: null,
|
|
44223
|
+
});
|
|
43772
44224
|
/**
|
|
43773
44225
|
* Handles risk rejection event.
|
|
43774
44226
|
* @param data - The risk contract data
|
|
@@ -43951,13 +44403,15 @@ class NotificationMemoryLiveUtils {
|
|
|
43951
44403
|
* Handles signal sync events (signal-open, signal-close).
|
|
43952
44404
|
* @param data - The signal sync contract data
|
|
43953
44405
|
*/
|
|
43954
|
-
this.handleSync = async (data) => {
|
|
44406
|
+
this.handleSync = trycatch(async (data) => {
|
|
43955
44407
|
bt.loggerService.info(NOTIFICATION_MEMORY_LIVE_METHOD_NAME_HANDLE_SYNC, {
|
|
43956
44408
|
signalId: data.signalId,
|
|
43957
44409
|
action: data.action,
|
|
43958
44410
|
});
|
|
43959
44411
|
this._addNotification(CREATE_SIGNAL_SYNC_NOTIFICATION_FN(data));
|
|
43960
|
-
}
|
|
44412
|
+
}, {
|
|
44413
|
+
defaultValue: null,
|
|
44414
|
+
});
|
|
43961
44415
|
/**
|
|
43962
44416
|
* Handles risk rejection event.
|
|
43963
44417
|
* @param data - The risk contract data
|
|
@@ -44066,8 +44520,10 @@ class NotificationDummyLiveUtils {
|
|
|
44066
44520
|
/**
|
|
44067
44521
|
* No-op handler for signal sync event.
|
|
44068
44522
|
*/
|
|
44069
|
-
this.handleSync = async () => {
|
|
44070
|
-
}
|
|
44523
|
+
this.handleSync = trycatch(async () => {
|
|
44524
|
+
}, {
|
|
44525
|
+
defaultValue: null,
|
|
44526
|
+
});
|
|
44071
44527
|
/**
|
|
44072
44528
|
* No-op handler for risk rejection event.
|
|
44073
44529
|
*/
|
|
@@ -44207,7 +44663,7 @@ class NotificationPersistLiveUtils {
|
|
|
44207
44663
|
* Handles signal sync events (signal-open, signal-close).
|
|
44208
44664
|
* @param data - The signal sync contract data
|
|
44209
44665
|
*/
|
|
44210
|
-
this.handleSync = async (data) => {
|
|
44666
|
+
this.handleSync = trycatch(async (data) => {
|
|
44211
44667
|
bt.loggerService.info(NOTIFICATION_PERSIST_LIVE_METHOD_NAME_HANDLE_SYNC, {
|
|
44212
44668
|
signalId: data.signalId,
|
|
44213
44669
|
action: data.action,
|
|
@@ -44215,7 +44671,9 @@ class NotificationPersistLiveUtils {
|
|
|
44215
44671
|
await this.waitForInit();
|
|
44216
44672
|
this._addNotification(CREATE_SIGNAL_SYNC_NOTIFICATION_FN(data));
|
|
44217
44673
|
await this._updateNotifications();
|
|
44218
|
-
}
|
|
44674
|
+
}, {
|
|
44675
|
+
defaultValue: null,
|
|
44676
|
+
});
|
|
44219
44677
|
/**
|
|
44220
44678
|
* Handles risk rejection event.
|
|
44221
44679
|
* @param data - The risk contract data
|
|
@@ -44377,9 +44835,11 @@ class NotificationBacktestAdapter {
|
|
|
44377
44835
|
* Proxies call to the underlying notification adapter.
|
|
44378
44836
|
* @param data - The signal sync contract data
|
|
44379
44837
|
*/
|
|
44380
|
-
this.handleSync = async (data) => {
|
|
44838
|
+
this.handleSync = trycatch(async (data) => {
|
|
44381
44839
|
return await this._notificationBacktestUtils.handleSync(data);
|
|
44382
|
-
}
|
|
44840
|
+
}, {
|
|
44841
|
+
defaultValue: null,
|
|
44842
|
+
});
|
|
44383
44843
|
/**
|
|
44384
44844
|
* Handles risk rejection event.
|
|
44385
44845
|
* Proxies call to the underlying notification adapter.
|
|
@@ -44521,9 +44981,11 @@ class NotificationLiveAdapter {
|
|
|
44521
44981
|
* Proxies call to the underlying notification adapter.
|
|
44522
44982
|
* @param data - The signal sync contract data
|
|
44523
44983
|
*/
|
|
44524
|
-
this.handleSync = async (data) => {
|
|
44984
|
+
this.handleSync = trycatch(async (data) => {
|
|
44525
44985
|
return await this._notificationLiveUtils.handleSync(data);
|
|
44526
|
-
}
|
|
44986
|
+
}, {
|
|
44987
|
+
defaultValue: null,
|
|
44988
|
+
});
|
|
44527
44989
|
/**
|
|
44528
44990
|
* Handles risk rejection event.
|
|
44529
44991
|
* Proxies call to the underlying notification adapter.
|