backtest-kit 2.2.7 → 2.2.9
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 +59 -21
- package/build/index.mjs +59 -21
- package/package.json +1 -1
- package/types.d.ts +5 -4
package/build/index.cjs
CHANGED
|
@@ -6554,6 +6554,40 @@ class RiskUtils {
|
|
|
6554
6554
|
*/
|
|
6555
6555
|
const Risk = new RiskUtils();
|
|
6556
6556
|
|
|
6557
|
+
/**
|
|
6558
|
+
* Emits signal tick results with correct execution context timestamp.
|
|
6559
|
+
* Wraps emitter calls in ExecutionContextService.runInContext to preserve
|
|
6560
|
+
* the temporal context from the tick's createdAt timestamp.
|
|
6561
|
+
*/
|
|
6562
|
+
const CALL_SIGNAL_EMIT_FN = functoolsKit.trycatch(beginTime(async (self, tick, context, isBacktest, symbol) => {
|
|
6563
|
+
await ExecutionContextService.runInContext(async () => {
|
|
6564
|
+
if (isBacktest) {
|
|
6565
|
+
await signalBacktestEmitter.next(tick);
|
|
6566
|
+
await self.actionCoreService.signalBacktest(isBacktest, tick, context);
|
|
6567
|
+
}
|
|
6568
|
+
if (!isBacktest) {
|
|
6569
|
+
await signalLiveEmitter.next(tick);
|
|
6570
|
+
await self.actionCoreService.signalLive(isBacktest, tick, context);
|
|
6571
|
+
}
|
|
6572
|
+
await signalEmitter.next(tick);
|
|
6573
|
+
await self.actionCoreService.signal(isBacktest, tick, context);
|
|
6574
|
+
}, {
|
|
6575
|
+
when: new Date(tick.createdAt),
|
|
6576
|
+
symbol: symbol,
|
|
6577
|
+
backtest: isBacktest,
|
|
6578
|
+
});
|
|
6579
|
+
}), {
|
|
6580
|
+
fallback: (error) => {
|
|
6581
|
+
const message = "StrategyConnectionService CALL_SIGNAL_EMIT_FN thrown";
|
|
6582
|
+
const payload = {
|
|
6583
|
+
error: functoolsKit.errorData(error),
|
|
6584
|
+
message: functoolsKit.getErrorMessage(error),
|
|
6585
|
+
};
|
|
6586
|
+
bt.loggerService.warn(message, payload);
|
|
6587
|
+
console.warn(message, payload);
|
|
6588
|
+
errorEmitter.next(error);
|
|
6589
|
+
},
|
|
6590
|
+
});
|
|
6557
6591
|
/**
|
|
6558
6592
|
* No-operation IRisk implementation.
|
|
6559
6593
|
* Always allows signals and performs no actions.
|
|
@@ -6926,16 +6960,7 @@ class StrategyConnectionService {
|
|
|
6926
6960
|
await strategy.waitForInit();
|
|
6927
6961
|
const tick = await strategy.tick(symbol, context.strategyName);
|
|
6928
6962
|
{
|
|
6929
|
-
|
|
6930
|
-
await signalBacktestEmitter.next(tick);
|
|
6931
|
-
await this.actionCoreService.signalBacktest(backtest, tick, context);
|
|
6932
|
-
}
|
|
6933
|
-
if (!this.executionContextService.context.backtest) {
|
|
6934
|
-
await signalLiveEmitter.next(tick);
|
|
6935
|
-
await this.actionCoreService.signalLive(backtest, tick, context);
|
|
6936
|
-
}
|
|
6937
|
-
await signalEmitter.next(tick);
|
|
6938
|
-
await this.actionCoreService.signal(backtest, tick, context);
|
|
6963
|
+
await CALL_SIGNAL_EMIT_FN(this, tick, context, backtest, symbol);
|
|
6939
6964
|
}
|
|
6940
6965
|
return tick;
|
|
6941
6966
|
};
|
|
@@ -6962,16 +6987,7 @@ class StrategyConnectionService {
|
|
|
6962
6987
|
await strategy.waitForInit();
|
|
6963
6988
|
const tick = await strategy.backtest(symbol, context.strategyName, candles);
|
|
6964
6989
|
{
|
|
6965
|
-
|
|
6966
|
-
await signalBacktestEmitter.next(tick);
|
|
6967
|
-
await this.actionCoreService.signalBacktest(backtest, tick, context);
|
|
6968
|
-
}
|
|
6969
|
-
if (!this.executionContextService.context.backtest) {
|
|
6970
|
-
await signalLiveEmitter.next(tick);
|
|
6971
|
-
await this.actionCoreService.signalLive(backtest, tick, context);
|
|
6972
|
-
}
|
|
6973
|
-
await signalEmitter.next(tick);
|
|
6974
|
-
await this.actionCoreService.signal(backtest, tick, context);
|
|
6990
|
+
await CALL_SIGNAL_EMIT_FN(this, tick, context, backtest, symbol);
|
|
6975
6991
|
}
|
|
6976
6992
|
return tick;
|
|
6977
6993
|
};
|
|
@@ -12001,6 +12017,7 @@ class BacktestLogicPrivateService {
|
|
|
12001
12017
|
this.exchangeCoreService = inject(TYPES.exchangeCoreService);
|
|
12002
12018
|
this.frameCoreService = inject(TYPES.frameCoreService);
|
|
12003
12019
|
this.methodContextService = inject(TYPES.methodContextService);
|
|
12020
|
+
this.actionCoreService = inject(TYPES.actionCoreService);
|
|
12004
12021
|
}
|
|
12005
12022
|
/**
|
|
12006
12023
|
* Runs backtest for a symbol, streaming closed signals as async generator.
|
|
@@ -12136,18 +12153,29 @@ class BacktestLogicPrivateService {
|
|
|
12136
12153
|
// и если активируется - продолжит с TP/SL мониторингом
|
|
12137
12154
|
let backtestResult;
|
|
12138
12155
|
let unScheduleOpen;
|
|
12156
|
+
let scheduleOpenResult;
|
|
12139
12157
|
{
|
|
12140
12158
|
const { strategyName, exchangeName, frameName } = this.methodContextService.context;
|
|
12141
12159
|
unScheduleOpen = backtestScheduleOpenSubject.filter((event) => {
|
|
12142
12160
|
let isOk = true;
|
|
12143
12161
|
{
|
|
12162
|
+
isOk = isOk && event.action === "opened";
|
|
12144
12163
|
isOk = isOk && event.strategyName === strategyName;
|
|
12145
12164
|
isOk = isOk && event.exchangeName === exchangeName;
|
|
12146
12165
|
isOk = isOk && event.frameName === frameName;
|
|
12147
12166
|
isOk = isOk && event.symbol === symbol;
|
|
12148
12167
|
}
|
|
12149
12168
|
return isOk;
|
|
12150
|
-
}).connect(async (tick) =>
|
|
12169
|
+
}).connect(async (tick) => {
|
|
12170
|
+
scheduleOpenResult = tick;
|
|
12171
|
+
await signalEmitter.next(tick);
|
|
12172
|
+
await signalBacktestEmitter.next(tick);
|
|
12173
|
+
await this.actionCoreService.signalBacktest(true, tick, {
|
|
12174
|
+
strategyName,
|
|
12175
|
+
exchangeName,
|
|
12176
|
+
frameName,
|
|
12177
|
+
});
|
|
12178
|
+
});
|
|
12151
12179
|
}
|
|
12152
12180
|
try {
|
|
12153
12181
|
backtestResult = await this.strategyCoreService.backtest(symbol, candles, when, true, {
|
|
@@ -12199,6 +12227,9 @@ class BacktestLogicPrivateService {
|
|
|
12199
12227
|
timeframes[i].getTime() < backtestResult.closeTimestamp) {
|
|
12200
12228
|
i++;
|
|
12201
12229
|
}
|
|
12230
|
+
if (scheduleOpenResult) {
|
|
12231
|
+
yield scheduleOpenResult;
|
|
12232
|
+
}
|
|
12202
12233
|
yield backtestResult;
|
|
12203
12234
|
// Check if strategy should stop after signal is closed
|
|
12204
12235
|
if (await this.strategyCoreService.getStopped(true, symbol, {
|
|
@@ -32411,6 +32442,7 @@ class NotificationInstance {
|
|
|
32411
32442
|
this._notifications = [];
|
|
32412
32443
|
/**
|
|
32413
32444
|
* Processes signal events and creates appropriate notifications.
|
|
32445
|
+
* Sorts signal notifications by createdAt to maintain chronological order.
|
|
32414
32446
|
*/
|
|
32415
32447
|
this._handleSignal = async (data) => {
|
|
32416
32448
|
if (data.action === "opened") {
|
|
@@ -32489,6 +32521,12 @@ class NotificationInstance {
|
|
|
32489
32521
|
createdAt: data.createdAt,
|
|
32490
32522
|
});
|
|
32491
32523
|
}
|
|
32524
|
+
// Sort signal notifications by createdAt (newest first)
|
|
32525
|
+
this._notifications.sort((a, b) => {
|
|
32526
|
+
const aCreatedAt = "createdAt" in a ? a.createdAt : 0;
|
|
32527
|
+
const bCreatedAt = "createdAt" in b ? b.createdAt : 0;
|
|
32528
|
+
return bCreatedAt - aCreatedAt;
|
|
32529
|
+
});
|
|
32492
32530
|
};
|
|
32493
32531
|
/**
|
|
32494
32532
|
* Processes partial profit events.
|
package/build/index.mjs
CHANGED
|
@@ -6534,6 +6534,40 @@ class RiskUtils {
|
|
|
6534
6534
|
*/
|
|
6535
6535
|
const Risk = new RiskUtils();
|
|
6536
6536
|
|
|
6537
|
+
/**
|
|
6538
|
+
* Emits signal tick results with correct execution context timestamp.
|
|
6539
|
+
* Wraps emitter calls in ExecutionContextService.runInContext to preserve
|
|
6540
|
+
* the temporal context from the tick's createdAt timestamp.
|
|
6541
|
+
*/
|
|
6542
|
+
const CALL_SIGNAL_EMIT_FN = trycatch(beginTime(async (self, tick, context, isBacktest, symbol) => {
|
|
6543
|
+
await ExecutionContextService.runInContext(async () => {
|
|
6544
|
+
if (isBacktest) {
|
|
6545
|
+
await signalBacktestEmitter.next(tick);
|
|
6546
|
+
await self.actionCoreService.signalBacktest(isBacktest, tick, context);
|
|
6547
|
+
}
|
|
6548
|
+
if (!isBacktest) {
|
|
6549
|
+
await signalLiveEmitter.next(tick);
|
|
6550
|
+
await self.actionCoreService.signalLive(isBacktest, tick, context);
|
|
6551
|
+
}
|
|
6552
|
+
await signalEmitter.next(tick);
|
|
6553
|
+
await self.actionCoreService.signal(isBacktest, tick, context);
|
|
6554
|
+
}, {
|
|
6555
|
+
when: new Date(tick.createdAt),
|
|
6556
|
+
symbol: symbol,
|
|
6557
|
+
backtest: isBacktest,
|
|
6558
|
+
});
|
|
6559
|
+
}), {
|
|
6560
|
+
fallback: (error) => {
|
|
6561
|
+
const message = "StrategyConnectionService CALL_SIGNAL_EMIT_FN thrown";
|
|
6562
|
+
const payload = {
|
|
6563
|
+
error: errorData(error),
|
|
6564
|
+
message: getErrorMessage(error),
|
|
6565
|
+
};
|
|
6566
|
+
bt.loggerService.warn(message, payload);
|
|
6567
|
+
console.warn(message, payload);
|
|
6568
|
+
errorEmitter.next(error);
|
|
6569
|
+
},
|
|
6570
|
+
});
|
|
6537
6571
|
/**
|
|
6538
6572
|
* No-operation IRisk implementation.
|
|
6539
6573
|
* Always allows signals and performs no actions.
|
|
@@ -6906,16 +6940,7 @@ class StrategyConnectionService {
|
|
|
6906
6940
|
await strategy.waitForInit();
|
|
6907
6941
|
const tick = await strategy.tick(symbol, context.strategyName);
|
|
6908
6942
|
{
|
|
6909
|
-
|
|
6910
|
-
await signalBacktestEmitter.next(tick);
|
|
6911
|
-
await this.actionCoreService.signalBacktest(backtest, tick, context);
|
|
6912
|
-
}
|
|
6913
|
-
if (!this.executionContextService.context.backtest) {
|
|
6914
|
-
await signalLiveEmitter.next(tick);
|
|
6915
|
-
await this.actionCoreService.signalLive(backtest, tick, context);
|
|
6916
|
-
}
|
|
6917
|
-
await signalEmitter.next(tick);
|
|
6918
|
-
await this.actionCoreService.signal(backtest, tick, context);
|
|
6943
|
+
await CALL_SIGNAL_EMIT_FN(this, tick, context, backtest, symbol);
|
|
6919
6944
|
}
|
|
6920
6945
|
return tick;
|
|
6921
6946
|
};
|
|
@@ -6942,16 +6967,7 @@ class StrategyConnectionService {
|
|
|
6942
6967
|
await strategy.waitForInit();
|
|
6943
6968
|
const tick = await strategy.backtest(symbol, context.strategyName, candles);
|
|
6944
6969
|
{
|
|
6945
|
-
|
|
6946
|
-
await signalBacktestEmitter.next(tick);
|
|
6947
|
-
await this.actionCoreService.signalBacktest(backtest, tick, context);
|
|
6948
|
-
}
|
|
6949
|
-
if (!this.executionContextService.context.backtest) {
|
|
6950
|
-
await signalLiveEmitter.next(tick);
|
|
6951
|
-
await this.actionCoreService.signalLive(backtest, tick, context);
|
|
6952
|
-
}
|
|
6953
|
-
await signalEmitter.next(tick);
|
|
6954
|
-
await this.actionCoreService.signal(backtest, tick, context);
|
|
6970
|
+
await CALL_SIGNAL_EMIT_FN(this, tick, context, backtest, symbol);
|
|
6955
6971
|
}
|
|
6956
6972
|
return tick;
|
|
6957
6973
|
};
|
|
@@ -11981,6 +11997,7 @@ class BacktestLogicPrivateService {
|
|
|
11981
11997
|
this.exchangeCoreService = inject(TYPES.exchangeCoreService);
|
|
11982
11998
|
this.frameCoreService = inject(TYPES.frameCoreService);
|
|
11983
11999
|
this.methodContextService = inject(TYPES.methodContextService);
|
|
12000
|
+
this.actionCoreService = inject(TYPES.actionCoreService);
|
|
11984
12001
|
}
|
|
11985
12002
|
/**
|
|
11986
12003
|
* Runs backtest for a symbol, streaming closed signals as async generator.
|
|
@@ -12116,18 +12133,29 @@ class BacktestLogicPrivateService {
|
|
|
12116
12133
|
// и если активируется - продолжит с TP/SL мониторингом
|
|
12117
12134
|
let backtestResult;
|
|
12118
12135
|
let unScheduleOpen;
|
|
12136
|
+
let scheduleOpenResult;
|
|
12119
12137
|
{
|
|
12120
12138
|
const { strategyName, exchangeName, frameName } = this.methodContextService.context;
|
|
12121
12139
|
unScheduleOpen = backtestScheduleOpenSubject.filter((event) => {
|
|
12122
12140
|
let isOk = true;
|
|
12123
12141
|
{
|
|
12142
|
+
isOk = isOk && event.action === "opened";
|
|
12124
12143
|
isOk = isOk && event.strategyName === strategyName;
|
|
12125
12144
|
isOk = isOk && event.exchangeName === exchangeName;
|
|
12126
12145
|
isOk = isOk && event.frameName === frameName;
|
|
12127
12146
|
isOk = isOk && event.symbol === symbol;
|
|
12128
12147
|
}
|
|
12129
12148
|
return isOk;
|
|
12130
|
-
}).connect(async (tick) =>
|
|
12149
|
+
}).connect(async (tick) => {
|
|
12150
|
+
scheduleOpenResult = tick;
|
|
12151
|
+
await signalEmitter.next(tick);
|
|
12152
|
+
await signalBacktestEmitter.next(tick);
|
|
12153
|
+
await this.actionCoreService.signalBacktest(true, tick, {
|
|
12154
|
+
strategyName,
|
|
12155
|
+
exchangeName,
|
|
12156
|
+
frameName,
|
|
12157
|
+
});
|
|
12158
|
+
});
|
|
12131
12159
|
}
|
|
12132
12160
|
try {
|
|
12133
12161
|
backtestResult = await this.strategyCoreService.backtest(symbol, candles, when, true, {
|
|
@@ -12179,6 +12207,9 @@ class BacktestLogicPrivateService {
|
|
|
12179
12207
|
timeframes[i].getTime() < backtestResult.closeTimestamp) {
|
|
12180
12208
|
i++;
|
|
12181
12209
|
}
|
|
12210
|
+
if (scheduleOpenResult) {
|
|
12211
|
+
yield scheduleOpenResult;
|
|
12212
|
+
}
|
|
12182
12213
|
yield backtestResult;
|
|
12183
12214
|
// Check if strategy should stop after signal is closed
|
|
12184
12215
|
if (await this.strategyCoreService.getStopped(true, symbol, {
|
|
@@ -32391,6 +32422,7 @@ class NotificationInstance {
|
|
|
32391
32422
|
this._notifications = [];
|
|
32392
32423
|
/**
|
|
32393
32424
|
* Processes signal events and creates appropriate notifications.
|
|
32425
|
+
* Sorts signal notifications by createdAt to maintain chronological order.
|
|
32394
32426
|
*/
|
|
32395
32427
|
this._handleSignal = async (data) => {
|
|
32396
32428
|
if (data.action === "opened") {
|
|
@@ -32469,6 +32501,12 @@ class NotificationInstance {
|
|
|
32469
32501
|
createdAt: data.createdAt,
|
|
32470
32502
|
});
|
|
32471
32503
|
}
|
|
32504
|
+
// Sort signal notifications by createdAt (newest first)
|
|
32505
|
+
this._notifications.sort((a, b) => {
|
|
32506
|
+
const aCreatedAt = "createdAt" in a ? a.createdAt : 0;
|
|
32507
|
+
const bCreatedAt = "createdAt" in b ? b.createdAt : 0;
|
|
32508
|
+
return bCreatedAt - aCreatedAt;
|
|
32509
|
+
});
|
|
32472
32510
|
};
|
|
32473
32511
|
/**
|
|
32474
32512
|
* Processes partial profit events.
|
package/package.json
CHANGED
package/types.d.ts
CHANGED
|
@@ -8899,7 +8899,7 @@ declare class BacktestUtils {
|
|
|
8899
8899
|
strategyName: StrategyName;
|
|
8900
8900
|
exchangeName: ExchangeName;
|
|
8901
8901
|
frameName: FrameName;
|
|
8902
|
-
}) => AsyncGenerator<IStrategyBacktestResult, void, unknown>;
|
|
8902
|
+
}) => AsyncGenerator<IStrategyTickResultOpened | IStrategyBacktestResult, void, unknown>;
|
|
8903
8903
|
/**
|
|
8904
8904
|
* Runs backtest in background without yielding results.
|
|
8905
8905
|
*
|
|
@@ -17436,6 +17436,7 @@ declare class BacktestLogicPrivateService {
|
|
|
17436
17436
|
private readonly exchangeCoreService;
|
|
17437
17437
|
private readonly frameCoreService;
|
|
17438
17438
|
private readonly methodContextService;
|
|
17439
|
+
private readonly actionCoreService;
|
|
17439
17440
|
/**
|
|
17440
17441
|
* Runs backtest for a symbol, streaming closed signals as async generator.
|
|
17441
17442
|
*
|
|
@@ -17450,7 +17451,7 @@ declare class BacktestLogicPrivateService {
|
|
|
17450
17451
|
* }
|
|
17451
17452
|
* ```
|
|
17452
17453
|
*/
|
|
17453
|
-
run(symbol: string): AsyncGenerator<IStrategyBacktestResult, void, unknown>;
|
|
17454
|
+
run(symbol: string): AsyncGenerator<IStrategyTickResultOpened | IStrategyBacktestResult, void, unknown>;
|
|
17454
17455
|
}
|
|
17455
17456
|
|
|
17456
17457
|
/**
|
|
@@ -17557,7 +17558,7 @@ declare class BacktestLogicPublicService implements TBacktestLogicPrivateService
|
|
|
17557
17558
|
strategyName: StrategyName;
|
|
17558
17559
|
exchangeName: ExchangeName;
|
|
17559
17560
|
frameName: FrameName;
|
|
17560
|
-
}) => AsyncGenerator<IStrategyBacktestResult, void, unknown>;
|
|
17561
|
+
}) => AsyncGenerator<IStrategyTickResultOpened | IStrategyBacktestResult, void, unknown>;
|
|
17561
17562
|
}
|
|
17562
17563
|
|
|
17563
17564
|
/**
|
|
@@ -17696,7 +17697,7 @@ declare class BacktestCommandService implements TBacktestLogicPublicService {
|
|
|
17696
17697
|
strategyName: StrategyName;
|
|
17697
17698
|
exchangeName: ExchangeName;
|
|
17698
17699
|
frameName: FrameName;
|
|
17699
|
-
}) => AsyncGenerator<IStrategyBacktestResult, void, unknown>;
|
|
17700
|
+
}) => AsyncGenerator<IStrategyTickResultOpened | IStrategyBacktestResult, void, unknown>;
|
|
17700
17701
|
}
|
|
17701
17702
|
|
|
17702
17703
|
/**
|