backtest-kit 1.5.44 → 1.5.45
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/README.md +1 -1
- package/build/index.cjs +70 -32
- package/build/index.mjs +71 -33
- package/package.json +1 -1
- package/types.d.ts +36 -12
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# 🧿 Backtest Kit
|
|
4
4
|
|
|
5
|
-
> A TypeScript framework for backtesting and live trading strategies on crypto
|
|
5
|
+
> A TypeScript framework for backtesting and live trading strategies on multi-asset, crypto or forex, with crash-safe persistence, signal validation, and AI optimization.
|
|
6
6
|
|
|
7
7
|

|
|
8
8
|
|
package/build/index.cjs
CHANGED
|
@@ -4175,16 +4175,30 @@ class SizingConnectionService {
|
|
|
4175
4175
|
}
|
|
4176
4176
|
}
|
|
4177
4177
|
|
|
4178
|
+
/**
|
|
4179
|
+
* Retrieves a value from an object using a given path.
|
|
4180
|
+
*
|
|
4181
|
+
* @param object - The object from which to retrieve the value.
|
|
4182
|
+
* @param path - The path to the desired value, either as an array or dot-separated string.
|
|
4183
|
+
* @returns - The value at the specified path, or undefined if it does not exist.
|
|
4184
|
+
*/
|
|
4185
|
+
const get = (object, path) => {
|
|
4186
|
+
const pathArray = Array.isArray(path) ? path : path.split('.').filter((key) => key);
|
|
4187
|
+
const pathArrayFlat = pathArray.flatMap((part) => typeof part === 'string' ? part.split('.') : part);
|
|
4188
|
+
return pathArrayFlat.reduce((obj, key) => obj && obj[key], object);
|
|
4189
|
+
};
|
|
4190
|
+
|
|
4191
|
+
/** Symbol indicating that a signal was rejected */
|
|
4192
|
+
const SYMBOL_REJECTED = Symbol("rejected");
|
|
4178
4193
|
/** Symbol indicating that positions need to be fetched from persistence */
|
|
4179
4194
|
const POSITION_NEED_FETCH = Symbol("risk-need-fetch");
|
|
4180
4195
|
/** Key generator for active position map */
|
|
4181
4196
|
const GET_KEY_FN = (strategyName, symbol) => `${strategyName}:${symbol}`;
|
|
4182
4197
|
/** Wrapper to execute risk validation function with error handling */
|
|
4183
4198
|
const DO_VALIDATION_FN = functoolsKit.trycatch(async (validation, params) => {
|
|
4184
|
-
await validation(params);
|
|
4185
|
-
return true;
|
|
4199
|
+
return await validation(params);
|
|
4186
4200
|
}, {
|
|
4187
|
-
defaultValue:
|
|
4201
|
+
defaultValue: SYMBOL_REJECTED,
|
|
4188
4202
|
fallback: (error) => {
|
|
4189
4203
|
const message = "ClientRisk exception thrown";
|
|
4190
4204
|
const payload = {
|
|
@@ -4204,7 +4218,9 @@ const DO_VALIDATION_FN = functoolsKit.trycatch(async (validation, params) => {
|
|
|
4204
4218
|
* In backtest mode, initializes with empty Map. In live mode, reads from persist storage.
|
|
4205
4219
|
*/
|
|
4206
4220
|
const WAIT_FOR_INIT_FN$1 = async (self) => {
|
|
4207
|
-
self.params.logger.debug("ClientRisk waitForInit", {
|
|
4221
|
+
self.params.logger.debug("ClientRisk waitForInit", {
|
|
4222
|
+
backtest: self.params.backtest,
|
|
4223
|
+
});
|
|
4208
4224
|
if (self.params.backtest) {
|
|
4209
4225
|
self._activePositions = new Map();
|
|
4210
4226
|
return;
|
|
@@ -4267,26 +4283,39 @@ class ClientRisk {
|
|
|
4267
4283
|
activePositionCount: riskMap.size,
|
|
4268
4284
|
activePositions: Array.from(riskMap.values()),
|
|
4269
4285
|
};
|
|
4270
|
-
|
|
4271
|
-
let isValid = true;
|
|
4272
|
-
let rejectionNote = "N/A";
|
|
4286
|
+
let rejectionResult = null;
|
|
4273
4287
|
if (this.params.validations) {
|
|
4274
4288
|
for (const validation of this.params.validations) {
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4289
|
+
const rejection = await DO_VALIDATION_FN(typeof validation === "function" ? validation : validation.validate, payload);
|
|
4290
|
+
if (!rejection) {
|
|
4291
|
+
continue;
|
|
4292
|
+
}
|
|
4293
|
+
if (typeof rejection === "symbol") {
|
|
4294
|
+
rejectionResult = {
|
|
4295
|
+
id: null,
|
|
4296
|
+
note: "note" in validation ? validation.note : "Validation failed",
|
|
4297
|
+
};
|
|
4298
|
+
break;
|
|
4299
|
+
}
|
|
4300
|
+
if (typeof rejection === "string") {
|
|
4301
|
+
rejectionResult = {
|
|
4302
|
+
id: null,
|
|
4303
|
+
note: rejection,
|
|
4304
|
+
};
|
|
4305
|
+
break;
|
|
4306
|
+
}
|
|
4307
|
+
if (functoolsKit.isObject(rejection)) {
|
|
4308
|
+
rejectionResult = {
|
|
4309
|
+
id: get(rejection, "id") || null,
|
|
4310
|
+
note: get(rejection, "note") || "Validation rejected the signal",
|
|
4311
|
+
};
|
|
4283
4312
|
break;
|
|
4284
4313
|
}
|
|
4285
4314
|
}
|
|
4286
4315
|
}
|
|
4287
|
-
if (
|
|
4316
|
+
if (rejectionResult) {
|
|
4288
4317
|
// Call params.onRejected for riskSubject emission
|
|
4289
|
-
await this.params.onRejected(params.symbol, params, riskMap.size,
|
|
4318
|
+
await this.params.onRejected(params.symbol, params, riskMap.size, rejectionResult, params.timestamp, this.params.backtest);
|
|
4290
4319
|
// Call schema callbacks.onRejected if defined
|
|
4291
4320
|
if (this.params.callbacks?.onRejected) {
|
|
4292
4321
|
this.params.callbacks.onRejected(params.symbol, params);
|
|
@@ -4365,18 +4394,19 @@ class ClientRisk {
|
|
|
4365
4394
|
* @param symbol - Trading pair symbol
|
|
4366
4395
|
* @param params - Risk check arguments
|
|
4367
4396
|
* @param activePositionCount - Number of active positions at rejection time
|
|
4368
|
-
* @param
|
|
4397
|
+
* @param rejectionResult - Rejection result with id and note
|
|
4369
4398
|
* @param timestamp - Event timestamp in milliseconds
|
|
4370
4399
|
* @param backtest - True if backtest mode, false if live mode
|
|
4371
4400
|
*/
|
|
4372
|
-
const COMMIT_REJECTION_FN = async (symbol, params, activePositionCount,
|
|
4401
|
+
const COMMIT_REJECTION_FN = async (symbol, params, activePositionCount, rejectionResult, timestamp, backtest) => await riskSubject.next({
|
|
4373
4402
|
symbol,
|
|
4374
4403
|
pendingSignal: params.pendingSignal,
|
|
4375
4404
|
strategyName: params.strategyName,
|
|
4376
4405
|
exchangeName: params.exchangeName,
|
|
4377
4406
|
currentPrice: params.currentPrice,
|
|
4378
4407
|
activePositionCount,
|
|
4379
|
-
|
|
4408
|
+
rejectionId: rejectionResult.id,
|
|
4409
|
+
rejectionNote: rejectionResult.note,
|
|
4380
4410
|
timestamp,
|
|
4381
4411
|
backtest,
|
|
4382
4412
|
});
|
|
@@ -7019,11 +7049,13 @@ const performance_columns = [
|
|
|
7019
7049
|
* - Signal identification (symbol, strategy name, signal ID, position)
|
|
7020
7050
|
* - Exchange information (exchange name, active position count)
|
|
7021
7051
|
* - Price data (open price, take profit, stop loss, current price)
|
|
7022
|
-
* - Rejection details (rejection reason
|
|
7052
|
+
* - Rejection details (rejection ID, rejection reason, timestamp)
|
|
7023
7053
|
*
|
|
7024
7054
|
* @remarks
|
|
7025
7055
|
* This configuration helps analyze when and why the risk management system rejected signals.
|
|
7026
|
-
* The "note" column visibility is controlled by {@link GLOBAL_CONFIG.CC_REPORT_SHOW_SIGNAL_NOTE}.
|
|
7056
|
+
* - The "note" column (signal note) visibility is controlled by {@link GLOBAL_CONFIG.CC_REPORT_SHOW_SIGNAL_NOTE}.
|
|
7057
|
+
* - The "rejectionNote" column (rejection reason) is always visible as it contains critical risk information.
|
|
7058
|
+
* - The "rejectionId" can be used to correlate rejections with signal IDs for debugging.
|
|
7027
7059
|
* Useful for tuning risk parameters and understanding risk control effectiveness.
|
|
7028
7060
|
*
|
|
7029
7061
|
* @example
|
|
@@ -7036,7 +7068,7 @@ const performance_columns = [
|
|
|
7036
7068
|
*
|
|
7037
7069
|
* // Or customize to focus on rejection reasons
|
|
7038
7070
|
* const customColumns = risk_columns.filter(col =>
|
|
7039
|
-
* ["symbol", "strategyName", "
|
|
7071
|
+
* ["symbol", "strategyName", "rejectionId", "rejectionNote", "activePositionCount", "timestamp"].includes(col.key)
|
|
7040
7072
|
* );
|
|
7041
7073
|
* await service.getReport("BTCUSDT", "my-strategy", customColumns);
|
|
7042
7074
|
* ```
|
|
@@ -7064,18 +7096,18 @@ const risk_columns = [
|
|
|
7064
7096
|
format: (data) => data.pendingSignal.id || "N/A",
|
|
7065
7097
|
isVisible: () => true,
|
|
7066
7098
|
},
|
|
7067
|
-
{
|
|
7068
|
-
key: "position",
|
|
7069
|
-
label: "Position",
|
|
7070
|
-
format: (data) => data.pendingSignal.position.toUpperCase(),
|
|
7071
|
-
isVisible: () => true,
|
|
7072
|
-
},
|
|
7073
7099
|
{
|
|
7074
7100
|
key: "note",
|
|
7075
7101
|
label: "Note",
|
|
7076
7102
|
format: (data) => toPlainString(data.pendingSignal.note ?? "N/A"),
|
|
7077
7103
|
isVisible: () => GLOBAL_CONFIG.CC_REPORT_SHOW_SIGNAL_NOTE,
|
|
7078
7104
|
},
|
|
7105
|
+
{
|
|
7106
|
+
key: "position",
|
|
7107
|
+
label: "Position",
|
|
7108
|
+
format: (data) => data.pendingSignal.position.toUpperCase(),
|
|
7109
|
+
isVisible: () => true,
|
|
7110
|
+
},
|
|
7079
7111
|
{
|
|
7080
7112
|
key: "exchangeName",
|
|
7081
7113
|
label: "Exchange",
|
|
@@ -7119,9 +7151,15 @@ const risk_columns = [
|
|
|
7119
7151
|
isVisible: () => true,
|
|
7120
7152
|
},
|
|
7121
7153
|
{
|
|
7122
|
-
key: "
|
|
7123
|
-
label: "
|
|
7124
|
-
format: (data) => data.
|
|
7154
|
+
key: "rejectionId",
|
|
7155
|
+
label: "ID",
|
|
7156
|
+
format: (data) => data.rejectionId ?? "N/A",
|
|
7157
|
+
isVisible: () => true,
|
|
7158
|
+
},
|
|
7159
|
+
{
|
|
7160
|
+
key: "rejectionNote",
|
|
7161
|
+
label: "Rejection Reason",
|
|
7162
|
+
format: (data) => data.rejectionNote,
|
|
7125
7163
|
isVisible: () => true,
|
|
7126
7164
|
},
|
|
7127
7165
|
{
|
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 { errorData, getErrorMessage, sleep, memoize, makeExtendable, singleshot, not, trycatch, retry, Subject, randomString,
|
|
3
|
+
import { errorData, getErrorMessage, sleep, memoize, makeExtendable, singleshot, not, trycatch, retry, Subject, randomString, isObject, ToolRegistry, and, resolveDocuments, str, iterateDocuments, distinctDocuments, queued, singlerun } from 'functools-kit';
|
|
4
4
|
import fs, { mkdir, writeFile } from 'fs/promises';
|
|
5
5
|
import path, { join } from 'path';
|
|
6
6
|
import crypto from 'crypto';
|
|
@@ -4173,16 +4173,30 @@ class SizingConnectionService {
|
|
|
4173
4173
|
}
|
|
4174
4174
|
}
|
|
4175
4175
|
|
|
4176
|
+
/**
|
|
4177
|
+
* Retrieves a value from an object using a given path.
|
|
4178
|
+
*
|
|
4179
|
+
* @param object - The object from which to retrieve the value.
|
|
4180
|
+
* @param path - The path to the desired value, either as an array or dot-separated string.
|
|
4181
|
+
* @returns - The value at the specified path, or undefined if it does not exist.
|
|
4182
|
+
*/
|
|
4183
|
+
const get = (object, path) => {
|
|
4184
|
+
const pathArray = Array.isArray(path) ? path : path.split('.').filter((key) => key);
|
|
4185
|
+
const pathArrayFlat = pathArray.flatMap((part) => typeof part === 'string' ? part.split('.') : part);
|
|
4186
|
+
return pathArrayFlat.reduce((obj, key) => obj && obj[key], object);
|
|
4187
|
+
};
|
|
4188
|
+
|
|
4189
|
+
/** Symbol indicating that a signal was rejected */
|
|
4190
|
+
const SYMBOL_REJECTED = Symbol("rejected");
|
|
4176
4191
|
/** Symbol indicating that positions need to be fetched from persistence */
|
|
4177
4192
|
const POSITION_NEED_FETCH = Symbol("risk-need-fetch");
|
|
4178
4193
|
/** Key generator for active position map */
|
|
4179
4194
|
const GET_KEY_FN = (strategyName, symbol) => `${strategyName}:${symbol}`;
|
|
4180
4195
|
/** Wrapper to execute risk validation function with error handling */
|
|
4181
4196
|
const DO_VALIDATION_FN = trycatch(async (validation, params) => {
|
|
4182
|
-
await validation(params);
|
|
4183
|
-
return true;
|
|
4197
|
+
return await validation(params);
|
|
4184
4198
|
}, {
|
|
4185
|
-
defaultValue:
|
|
4199
|
+
defaultValue: SYMBOL_REJECTED,
|
|
4186
4200
|
fallback: (error) => {
|
|
4187
4201
|
const message = "ClientRisk exception thrown";
|
|
4188
4202
|
const payload = {
|
|
@@ -4202,7 +4216,9 @@ const DO_VALIDATION_FN = trycatch(async (validation, params) => {
|
|
|
4202
4216
|
* In backtest mode, initializes with empty Map. In live mode, reads from persist storage.
|
|
4203
4217
|
*/
|
|
4204
4218
|
const WAIT_FOR_INIT_FN$1 = async (self) => {
|
|
4205
|
-
self.params.logger.debug("ClientRisk waitForInit", {
|
|
4219
|
+
self.params.logger.debug("ClientRisk waitForInit", {
|
|
4220
|
+
backtest: self.params.backtest,
|
|
4221
|
+
});
|
|
4206
4222
|
if (self.params.backtest) {
|
|
4207
4223
|
self._activePositions = new Map();
|
|
4208
4224
|
return;
|
|
@@ -4265,26 +4281,39 @@ class ClientRisk {
|
|
|
4265
4281
|
activePositionCount: riskMap.size,
|
|
4266
4282
|
activePositions: Array.from(riskMap.values()),
|
|
4267
4283
|
};
|
|
4268
|
-
|
|
4269
|
-
let isValid = true;
|
|
4270
|
-
let rejectionNote = "N/A";
|
|
4284
|
+
let rejectionResult = null;
|
|
4271
4285
|
if (this.params.validations) {
|
|
4272
4286
|
for (const validation of this.params.validations) {
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4287
|
+
const rejection = await DO_VALIDATION_FN(typeof validation === "function" ? validation : validation.validate, payload);
|
|
4288
|
+
if (!rejection) {
|
|
4289
|
+
continue;
|
|
4290
|
+
}
|
|
4291
|
+
if (typeof rejection === "symbol") {
|
|
4292
|
+
rejectionResult = {
|
|
4293
|
+
id: null,
|
|
4294
|
+
note: "note" in validation ? validation.note : "Validation failed",
|
|
4295
|
+
};
|
|
4296
|
+
break;
|
|
4297
|
+
}
|
|
4298
|
+
if (typeof rejection === "string") {
|
|
4299
|
+
rejectionResult = {
|
|
4300
|
+
id: null,
|
|
4301
|
+
note: rejection,
|
|
4302
|
+
};
|
|
4303
|
+
break;
|
|
4304
|
+
}
|
|
4305
|
+
if (isObject(rejection)) {
|
|
4306
|
+
rejectionResult = {
|
|
4307
|
+
id: get(rejection, "id") || null,
|
|
4308
|
+
note: get(rejection, "note") || "Validation rejected the signal",
|
|
4309
|
+
};
|
|
4281
4310
|
break;
|
|
4282
4311
|
}
|
|
4283
4312
|
}
|
|
4284
4313
|
}
|
|
4285
|
-
if (
|
|
4314
|
+
if (rejectionResult) {
|
|
4286
4315
|
// Call params.onRejected for riskSubject emission
|
|
4287
|
-
await this.params.onRejected(params.symbol, params, riskMap.size,
|
|
4316
|
+
await this.params.onRejected(params.symbol, params, riskMap.size, rejectionResult, params.timestamp, this.params.backtest);
|
|
4288
4317
|
// Call schema callbacks.onRejected if defined
|
|
4289
4318
|
if (this.params.callbacks?.onRejected) {
|
|
4290
4319
|
this.params.callbacks.onRejected(params.symbol, params);
|
|
@@ -4363,18 +4392,19 @@ class ClientRisk {
|
|
|
4363
4392
|
* @param symbol - Trading pair symbol
|
|
4364
4393
|
* @param params - Risk check arguments
|
|
4365
4394
|
* @param activePositionCount - Number of active positions at rejection time
|
|
4366
|
-
* @param
|
|
4395
|
+
* @param rejectionResult - Rejection result with id and note
|
|
4367
4396
|
* @param timestamp - Event timestamp in milliseconds
|
|
4368
4397
|
* @param backtest - True if backtest mode, false if live mode
|
|
4369
4398
|
*/
|
|
4370
|
-
const COMMIT_REJECTION_FN = async (symbol, params, activePositionCount,
|
|
4399
|
+
const COMMIT_REJECTION_FN = async (symbol, params, activePositionCount, rejectionResult, timestamp, backtest) => await riskSubject.next({
|
|
4371
4400
|
symbol,
|
|
4372
4401
|
pendingSignal: params.pendingSignal,
|
|
4373
4402
|
strategyName: params.strategyName,
|
|
4374
4403
|
exchangeName: params.exchangeName,
|
|
4375
4404
|
currentPrice: params.currentPrice,
|
|
4376
4405
|
activePositionCount,
|
|
4377
|
-
|
|
4406
|
+
rejectionId: rejectionResult.id,
|
|
4407
|
+
rejectionNote: rejectionResult.note,
|
|
4378
4408
|
timestamp,
|
|
4379
4409
|
backtest,
|
|
4380
4410
|
});
|
|
@@ -7017,11 +7047,13 @@ const performance_columns = [
|
|
|
7017
7047
|
* - Signal identification (symbol, strategy name, signal ID, position)
|
|
7018
7048
|
* - Exchange information (exchange name, active position count)
|
|
7019
7049
|
* - Price data (open price, take profit, stop loss, current price)
|
|
7020
|
-
* - Rejection details (rejection reason
|
|
7050
|
+
* - Rejection details (rejection ID, rejection reason, timestamp)
|
|
7021
7051
|
*
|
|
7022
7052
|
* @remarks
|
|
7023
7053
|
* This configuration helps analyze when and why the risk management system rejected signals.
|
|
7024
|
-
* The "note" column visibility is controlled by {@link GLOBAL_CONFIG.CC_REPORT_SHOW_SIGNAL_NOTE}.
|
|
7054
|
+
* - The "note" column (signal note) visibility is controlled by {@link GLOBAL_CONFIG.CC_REPORT_SHOW_SIGNAL_NOTE}.
|
|
7055
|
+
* - The "rejectionNote" column (rejection reason) is always visible as it contains critical risk information.
|
|
7056
|
+
* - The "rejectionId" can be used to correlate rejections with signal IDs for debugging.
|
|
7025
7057
|
* Useful for tuning risk parameters and understanding risk control effectiveness.
|
|
7026
7058
|
*
|
|
7027
7059
|
* @example
|
|
@@ -7034,7 +7066,7 @@ const performance_columns = [
|
|
|
7034
7066
|
*
|
|
7035
7067
|
* // Or customize to focus on rejection reasons
|
|
7036
7068
|
* const customColumns = risk_columns.filter(col =>
|
|
7037
|
-
* ["symbol", "strategyName", "
|
|
7069
|
+
* ["symbol", "strategyName", "rejectionId", "rejectionNote", "activePositionCount", "timestamp"].includes(col.key)
|
|
7038
7070
|
* );
|
|
7039
7071
|
* await service.getReport("BTCUSDT", "my-strategy", customColumns);
|
|
7040
7072
|
* ```
|
|
@@ -7062,18 +7094,18 @@ const risk_columns = [
|
|
|
7062
7094
|
format: (data) => data.pendingSignal.id || "N/A",
|
|
7063
7095
|
isVisible: () => true,
|
|
7064
7096
|
},
|
|
7065
|
-
{
|
|
7066
|
-
key: "position",
|
|
7067
|
-
label: "Position",
|
|
7068
|
-
format: (data) => data.pendingSignal.position.toUpperCase(),
|
|
7069
|
-
isVisible: () => true,
|
|
7070
|
-
},
|
|
7071
7097
|
{
|
|
7072
7098
|
key: "note",
|
|
7073
7099
|
label: "Note",
|
|
7074
7100
|
format: (data) => toPlainString(data.pendingSignal.note ?? "N/A"),
|
|
7075
7101
|
isVisible: () => GLOBAL_CONFIG.CC_REPORT_SHOW_SIGNAL_NOTE,
|
|
7076
7102
|
},
|
|
7103
|
+
{
|
|
7104
|
+
key: "position",
|
|
7105
|
+
label: "Position",
|
|
7106
|
+
format: (data) => data.pendingSignal.position.toUpperCase(),
|
|
7107
|
+
isVisible: () => true,
|
|
7108
|
+
},
|
|
7077
7109
|
{
|
|
7078
7110
|
key: "exchangeName",
|
|
7079
7111
|
label: "Exchange",
|
|
@@ -7117,9 +7149,15 @@ const risk_columns = [
|
|
|
7117
7149
|
isVisible: () => true,
|
|
7118
7150
|
},
|
|
7119
7151
|
{
|
|
7120
|
-
key: "
|
|
7121
|
-
label: "
|
|
7122
|
-
format: (data) => data.
|
|
7152
|
+
key: "rejectionId",
|
|
7153
|
+
label: "ID",
|
|
7154
|
+
format: (data) => data.rejectionId ?? "N/A",
|
|
7155
|
+
isVisible: () => true,
|
|
7156
|
+
},
|
|
7157
|
+
{
|
|
7158
|
+
key: "rejectionNote",
|
|
7159
|
+
label: "Rejection Reason",
|
|
7160
|
+
format: (data) => data.rejectionNote,
|
|
7123
7161
|
isVisible: () => true,
|
|
7124
7162
|
},
|
|
7125
7163
|
{
|
package/package.json
CHANGED
package/types.d.ts
CHANGED
|
@@ -759,6 +759,11 @@ declare const MethodContextService: (new () => {
|
|
|
759
759
|
};
|
|
760
760
|
}, "prototype"> & di_scoped.IScopedClassRun<[context: IMethodContext]>;
|
|
761
761
|
|
|
762
|
+
/**
|
|
763
|
+
* Risk rejection result type.
|
|
764
|
+
* Can be void, null, or an IRiskRejectionResult object.
|
|
765
|
+
*/
|
|
766
|
+
type RiskRejection = void | IRiskRejectionResult | string | null;
|
|
762
767
|
/**
|
|
763
768
|
* Risk check arguments for evaluating whether to allow opening a new position.
|
|
764
769
|
* Called BEFORE signal creation to validate if conditions allow new signals.
|
|
@@ -812,12 +817,23 @@ interface IRiskValidationPayload extends IRiskCheckArgs {
|
|
|
812
817
|
/** List of currently active positions across all strategies */
|
|
813
818
|
activePositions: IRiskActivePosition[];
|
|
814
819
|
}
|
|
820
|
+
/**
|
|
821
|
+
* Risk validation rejection result.
|
|
822
|
+
* Returned when validation fails, contains debugging information.
|
|
823
|
+
*/
|
|
824
|
+
interface IRiskRejectionResult {
|
|
825
|
+
/** Unique identifier for this rejection instance */
|
|
826
|
+
id: string | null;
|
|
827
|
+
/** Human-readable reason for rejection */
|
|
828
|
+
note: string;
|
|
829
|
+
}
|
|
815
830
|
/**
|
|
816
831
|
* Risk validation function type.
|
|
817
|
-
*
|
|
832
|
+
* Returns null/void if validation passes, IRiskRejectionResult if validation fails.
|
|
833
|
+
* Can also throw error which will be caught and converted to IRiskRejectionResult.
|
|
818
834
|
*/
|
|
819
835
|
interface IRiskValidationFn {
|
|
820
|
-
(payload: IRiskValidationPayload):
|
|
836
|
+
(payload: IRiskValidationPayload): RiskRejection | Promise<RiskRejection>;
|
|
821
837
|
}
|
|
822
838
|
/**
|
|
823
839
|
* Risk validation configuration.
|
|
@@ -865,11 +881,11 @@ interface IRiskParams extends IRiskSchema {
|
|
|
865
881
|
* @param symbol - Trading pair symbol
|
|
866
882
|
* @param params - Risk check arguments
|
|
867
883
|
* @param activePositionCount - Number of active positions at rejection time
|
|
868
|
-
* @param
|
|
884
|
+
* @param rejectionResult - Rejection result with id and note
|
|
869
885
|
* @param timestamp - Event timestamp in milliseconds
|
|
870
886
|
* @param backtest - True if backtest mode, false if live mode
|
|
871
887
|
*/
|
|
872
|
-
onRejected: (symbol: string, params: IRiskCheckArgs, activePositionCount: number,
|
|
888
|
+
onRejected: (symbol: string, params: IRiskCheckArgs, activePositionCount: number, rejectionResult: IRiskRejectionResult, timestamp: number, backtest: boolean) => void | Promise<void>;
|
|
873
889
|
}
|
|
874
890
|
/**
|
|
875
891
|
* Risk interface implemented by ClientRisk.
|
|
@@ -3124,16 +3140,22 @@ interface RiskContract {
|
|
|
3124
3140
|
*/
|
|
3125
3141
|
activePositionCount: number;
|
|
3126
3142
|
/**
|
|
3127
|
-
*
|
|
3128
|
-
*
|
|
3143
|
+
* Unique identifier for this rejection instance.
|
|
3144
|
+
* Generated by ClientRisk for tracking and debugging purposes.
|
|
3145
|
+
* Null if validation threw exception without custom ID.
|
|
3146
|
+
*/
|
|
3147
|
+
rejectionId: string | null;
|
|
3148
|
+
/**
|
|
3149
|
+
* Human-readable reason why the signal was rejected.
|
|
3150
|
+
* Captured from IRiskValidation.note or error message.
|
|
3129
3151
|
*
|
|
3130
3152
|
* @example
|
|
3131
3153
|
* ```typescript
|
|
3132
|
-
* console.log(`Rejection reason: ${event.
|
|
3154
|
+
* console.log(`Rejection reason: ${event.rejectionNote}`);
|
|
3133
3155
|
* // Output: "Rejection reason: Max 3 positions allowed"
|
|
3134
3156
|
* ```
|
|
3135
3157
|
*/
|
|
3136
|
-
|
|
3158
|
+
rejectionNote: string;
|
|
3137
3159
|
/**
|
|
3138
3160
|
* Event timestamp in milliseconds since Unix epoch.
|
|
3139
3161
|
* Represents when the signal was rejected.
|
|
@@ -4540,8 +4562,10 @@ interface RiskEvent {
|
|
|
4540
4562
|
currentPrice: number;
|
|
4541
4563
|
/** Number of active positions at rejection time */
|
|
4542
4564
|
activePositionCount: number;
|
|
4565
|
+
/** Unique identifier for this rejection instance (null if validation threw exception without custom ID) */
|
|
4566
|
+
rejectionId: string | null;
|
|
4543
4567
|
/** Rejection reason from validation note */
|
|
4544
|
-
|
|
4568
|
+
rejectionNote: string;
|
|
4545
4569
|
/** Whether this event is from backtest mode (true) or live mode (false) */
|
|
4546
4570
|
backtest: boolean;
|
|
4547
4571
|
}
|
|
@@ -5348,7 +5372,7 @@ declare class BacktestUtils {
|
|
|
5348
5372
|
id: string;
|
|
5349
5373
|
symbol: string;
|
|
5350
5374
|
strategyName: string;
|
|
5351
|
-
status: "
|
|
5375
|
+
status: "rejected" | "pending" | "fulfilled" | "ready";
|
|
5352
5376
|
}[]>;
|
|
5353
5377
|
}
|
|
5354
5378
|
/**
|
|
@@ -5714,7 +5738,7 @@ declare class LiveUtils {
|
|
|
5714
5738
|
id: string;
|
|
5715
5739
|
symbol: string;
|
|
5716
5740
|
strategyName: string;
|
|
5717
|
-
status: "
|
|
5741
|
+
status: "rejected" | "pending" | "fulfilled" | "ready";
|
|
5718
5742
|
}[]>;
|
|
5719
5743
|
}
|
|
5720
5744
|
/**
|
|
@@ -6597,7 +6621,7 @@ declare class WalkerUtils {
|
|
|
6597
6621
|
id: string;
|
|
6598
6622
|
symbol: string;
|
|
6599
6623
|
walkerName: string;
|
|
6600
|
-
status: "
|
|
6624
|
+
status: "rejected" | "pending" | "fulfilled" | "ready";
|
|
6601
6625
|
}[]>;
|
|
6602
6626
|
}
|
|
6603
6627
|
/**
|