backtest-kit 13.5.0 → 13.6.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 +403 -1
- package/build/index.mjs +403 -1
- package/package.json +1 -1
- package/types.d.ts +299 -2
package/build/index.mjs
CHANGED
|
@@ -629,6 +629,15 @@ const DEFAULT_CONFIG = Object.freeze({ ...GLOBAL_CONFIG });
|
|
|
629
629
|
* Consumers should implement retry logic in their listeners to handle transient synchronization failures.
|
|
630
630
|
*/
|
|
631
631
|
const syncSubject = new Subject();
|
|
632
|
+
/**
|
|
633
|
+
* Pending-order synchronization emitter.
|
|
634
|
+
* Emitted on every live tick while a pending signal is monitored, BEFORE TP/SL/time evaluation.
|
|
635
|
+
* Asks the exchange whether the order is STILL pending (open).
|
|
636
|
+
*
|
|
637
|
+
* If a listener returns false OR throws, the order is treated as no longer open on the exchange
|
|
638
|
+
* and the framework closes the pending signal with closeReason "closed". Never emitted in backtest.
|
|
639
|
+
*/
|
|
640
|
+
const syncPendingSubject = new Subject();
|
|
632
641
|
/**
|
|
633
642
|
* Global signal emitter for all trading events (live + backtest).
|
|
634
643
|
* Emits all signal events regardless of execution mode.
|
|
@@ -836,6 +845,7 @@ var emitters = /*#__PURE__*/Object.freeze({
|
|
|
836
845
|
signalLiveEmitter: signalLiveEmitter,
|
|
837
846
|
signalNotifySubject: signalNotifySubject,
|
|
838
847
|
strategyCommitSubject: strategyCommitSubject,
|
|
848
|
+
syncPendingSubject: syncPendingSubject,
|
|
839
849
|
syncSubject: syncSubject,
|
|
840
850
|
validationSubject: validationSubject,
|
|
841
851
|
walkerCompleteSubject: walkerCompleteSubject,
|
|
@@ -7055,6 +7065,64 @@ const CALL_SIGNAL_SYNC_CLOSE_FN = trycatch(async (timestamp, currentPrice, close
|
|
|
7055
7065
|
errorEmitter.next(error);
|
|
7056
7066
|
}
|
|
7057
7067
|
});
|
|
7068
|
+
/**
|
|
7069
|
+
* Calls onSignalPing callback for the pending-order synchronization event.
|
|
7070
|
+
*
|
|
7071
|
+
* Invoked at the start of the pending-signal monitoring block on every LIVE tick, BEFORE the
|
|
7072
|
+
* framework evaluates TP/SL/time completion. It asks the external order management system
|
|
7073
|
+
* whether the order backing this position is STILL pending (open) on the exchange.
|
|
7074
|
+
*
|
|
7075
|
+
* The Subject `await .next()` propagates listener exceptions passthrough, so the trycatch wrapper
|
|
7076
|
+
* collapses both a thrown listener and an explicit `false` into `false` (defaultValue). A `false`
|
|
7077
|
+
* result means the order is no longer open on the exchange and the caller closes the position with
|
|
7078
|
+
* closeReason "closed". A missing/true result keeps the position under normal TP/SL monitoring.
|
|
7079
|
+
*/
|
|
7080
|
+
const CALL_SIGNAL_PING_FN = trycatch(async (timestamp, currentPrice, signal, self) => {
|
|
7081
|
+
const publicSignal = TO_PUBLIC_SIGNAL("pending", signal, currentPrice);
|
|
7082
|
+
return await self.params.onSignalPing({
|
|
7083
|
+
action: "signal-ping",
|
|
7084
|
+
symbol: self.params.execution.context.symbol,
|
|
7085
|
+
strategyName: self.params.strategyName,
|
|
7086
|
+
exchangeName: self.params.exchangeName,
|
|
7087
|
+
frameName: self.params.frameName,
|
|
7088
|
+
backtest: self.params.execution.context.backtest,
|
|
7089
|
+
signalId: signal.id,
|
|
7090
|
+
timestamp,
|
|
7091
|
+
signal: publicSignal,
|
|
7092
|
+
currentPrice,
|
|
7093
|
+
pnl: publicSignal.pnl,
|
|
7094
|
+
peakProfit: publicSignal.peakProfit,
|
|
7095
|
+
maxDrawdown: publicSignal.maxDrawdown,
|
|
7096
|
+
position: publicSignal.position,
|
|
7097
|
+
priceOpen: publicSignal.priceOpen,
|
|
7098
|
+
priceTakeProfit: publicSignal.priceTakeProfit,
|
|
7099
|
+
priceStopLoss: publicSignal.priceStopLoss,
|
|
7100
|
+
originalPriceTakeProfit: publicSignal.originalPriceTakeProfit,
|
|
7101
|
+
originalPriceStopLoss: publicSignal.originalPriceStopLoss,
|
|
7102
|
+
originalPriceOpen: publicSignal.originalPriceOpen,
|
|
7103
|
+
scheduledAt: publicSignal.scheduledAt,
|
|
7104
|
+
pendingAt: publicSignal.pendingAt,
|
|
7105
|
+
totalEntries: publicSignal.totalEntries,
|
|
7106
|
+
totalPartials: publicSignal.totalPartials,
|
|
7107
|
+
});
|
|
7108
|
+
}, {
|
|
7109
|
+
defaultValue: false,
|
|
7110
|
+
fallback: (error, timestamp, currentPrice, signal, self) => {
|
|
7111
|
+
const message = "ClientStrategy CALL_SIGNAL_PING_FN thrown";
|
|
7112
|
+
const payload = {
|
|
7113
|
+
error: errorData(error),
|
|
7114
|
+
message: getErrorMessage(error),
|
|
7115
|
+
data: {
|
|
7116
|
+
timestamp,
|
|
7117
|
+
currentPrice,
|
|
7118
|
+
signalId: signal.id,
|
|
7119
|
+
}
|
|
7120
|
+
};
|
|
7121
|
+
self.params.logger.warn(message, payload);
|
|
7122
|
+
console.warn(message, payload);
|
|
7123
|
+
errorEmitter.next(error);
|
|
7124
|
+
}
|
|
7125
|
+
});
|
|
7058
7126
|
/**
|
|
7059
7127
|
* Calls onCommit callback with strategy commit event.
|
|
7060
7128
|
*
|
|
@@ -8976,6 +9044,47 @@ const CLOSE_PENDING_SIGNAL_FN = async (self, signal, currentPrice, closeReason)
|
|
|
8976
9044
|
await CALL_TICK_CALLBACKS_FN(self, self.params.execution.context.symbol, result, currentTime, self.params.execution.context.backtest);
|
|
8977
9045
|
return result;
|
|
8978
9046
|
};
|
|
9047
|
+
/**
|
|
9048
|
+
* Closes the pending signal with closeReason "closed" after the pending-order ping reported the
|
|
9049
|
+
* order is no longer open on the exchange (CALL_SIGNAL_PING_FN returned false / threw).
|
|
9050
|
+
*
|
|
9051
|
+
* Unlike CLOSE_PENDING_SIGNAL_FN this does NOT re-confirm via onSignalSync — the ping already
|
|
9052
|
+
* established the order is gone, so re-asking the broker would be redundant. Runs the same teardown
|
|
9053
|
+
* (close callback, partial/breakeven clear, risk remove, setPendingSignal(null)). Live-only path.
|
|
9054
|
+
*/
|
|
9055
|
+
const CLOSE_PENDING_SIGNAL_AS_CLOSED_FN = async (self, signal, currentPrice) => {
|
|
9056
|
+
const currentTime = self.params.execution.context.when.getTime();
|
|
9057
|
+
const publicSignal = TO_PUBLIC_SIGNAL("pending", signal, currentPrice);
|
|
9058
|
+
self.params.logger.info("ClientStrategy signal closed by pending-order ping (order no longer open on exchange)", {
|
|
9059
|
+
symbol: self.params.execution.context.symbol,
|
|
9060
|
+
signalId: signal.id,
|
|
9061
|
+
priceClose: currentPrice,
|
|
9062
|
+
pnlPercentage: publicSignal.pnl.pnlPercentage,
|
|
9063
|
+
});
|
|
9064
|
+
await CALL_CLOSE_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, currentPrice, currentTime, self.params.execution.context.backtest);
|
|
9065
|
+
// КРИТИЧНО: Очищаем состояние ClientPartial при закрытии позиции
|
|
9066
|
+
await CALL_PARTIAL_CLEAR_FN(self, self.params.execution.context.symbol, signal, currentPrice, currentTime, self.params.execution.context.backtest);
|
|
9067
|
+
// КРИТИЧНО: Очищаем состояние ClientBreakeven при закрытии позиции
|
|
9068
|
+
await CALL_BREAKEVEN_CLEAR_FN(self, self.params.execution.context.symbol, signal, currentPrice, currentTime, self.params.execution.context.backtest);
|
|
9069
|
+
await CALL_RISK_REMOVE_SIGNAL_FN(self, self.params.execution.context.symbol, currentTime, self.params.execution.context.backtest);
|
|
9070
|
+
await self.setPendingSignal(null, currentPrice);
|
|
9071
|
+
const result = {
|
|
9072
|
+
action: "closed",
|
|
9073
|
+
signal: publicSignal,
|
|
9074
|
+
currentPrice: currentPrice,
|
|
9075
|
+
closeReason: "closed",
|
|
9076
|
+
closeTimestamp: currentTime,
|
|
9077
|
+
pnl: publicSignal.pnl,
|
|
9078
|
+
strategyName: self.params.method.context.strategyName,
|
|
9079
|
+
exchangeName: self.params.method.context.exchangeName,
|
|
9080
|
+
frameName: self.params.method.context.frameName,
|
|
9081
|
+
symbol: self.params.execution.context.symbol,
|
|
9082
|
+
backtest: self.params.execution.context.backtest,
|
|
9083
|
+
createdAt: currentTime,
|
|
9084
|
+
};
|
|
9085
|
+
await CALL_TICK_CALLBACKS_FN(self, self.params.execution.context.symbol, result, currentTime, self.params.execution.context.backtest);
|
|
9086
|
+
return result;
|
|
9087
|
+
};
|
|
8979
9088
|
const RETURN_PENDING_SIGNAL_ACTIVE_FN = async (self, signal, currentPrice, backtest) => {
|
|
8980
9089
|
let percentTp = 0;
|
|
8981
9090
|
let percentSl = 0;
|
|
@@ -11013,6 +11122,16 @@ class ClientStrategy {
|
|
|
11013
11122
|
}
|
|
11014
11123
|
// Monitor pending signal
|
|
11015
11124
|
const averagePrice = await this.params.exchange.getAveragePrice(this.params.execution.context.symbol);
|
|
11125
|
+
// Pending-order ping: before evaluating TP/SL/time, confirm the order is STILL open on the
|
|
11126
|
+
// exchange. CALL_SIGNAL_PING_FN returns false when the listener returns false OR throws
|
|
11127
|
+
// (Subject .next passthrough), meaning the order is no longer pending — close with "closed".
|
|
11128
|
+
// Skipped in backtest: there is no live exchange to query.
|
|
11129
|
+
if (!this.params.execution.context.backtest) {
|
|
11130
|
+
const stillPending = await CALL_SIGNAL_PING_FN(currentTime, averagePrice, this._pendingSignal, this);
|
|
11131
|
+
if (!stillPending) {
|
|
11132
|
+
return await CLOSE_PENDING_SIGNAL_AS_CLOSED_FN(this, this._pendingSignal, averagePrice);
|
|
11133
|
+
}
|
|
11134
|
+
}
|
|
11016
11135
|
const closedResult = await CHECK_PENDING_SIGNAL_COMPLETION_FN(this, this._pendingSignal, averagePrice);
|
|
11017
11136
|
if (closedResult) {
|
|
11018
11137
|
return closedResult;
|
|
@@ -12861,6 +12980,32 @@ const CREATE_SYNC_FN = (self, strategyName, exchangeName, frameName, backtest) =
|
|
|
12861
12980
|
},
|
|
12862
12981
|
defaultValue: false,
|
|
12863
12982
|
});
|
|
12983
|
+
/**
|
|
12984
|
+
* If the syncPendingSubject listener or any registered action throws, it means the order backing the
|
|
12985
|
+
* open position is no longer pending on the exchange (filled/cancelled/liquidated externally).
|
|
12986
|
+
* The trycatch wrapper collapses a throw OR an explicit false into false, and ClientStrategy closes
|
|
12987
|
+
* the pending signal with closeReason "closed". Skipped in backtest — there is no live exchange.
|
|
12988
|
+
*/
|
|
12989
|
+
const CREATE_SYNC_PENDING_FN = (self, strategyName, exchangeName, frameName, backtest) => trycatch(async (event) => {
|
|
12990
|
+
if (event.backtest) {
|
|
12991
|
+
return true;
|
|
12992
|
+
}
|
|
12993
|
+
await syncPendingSubject.next(event);
|
|
12994
|
+
await self.actionCoreService.orderPing(backtest, event, { strategyName, exchangeName, frameName });
|
|
12995
|
+
return true;
|
|
12996
|
+
}, {
|
|
12997
|
+
fallback: (error) => {
|
|
12998
|
+
const message = "StrategyConnectionService CREATE_SYNC_PENDING_FN thrown. Order no longer pending on exchange";
|
|
12999
|
+
const payload = {
|
|
13000
|
+
error: errorData(error),
|
|
13001
|
+
message: getErrorMessage(error),
|
|
13002
|
+
};
|
|
13003
|
+
self.loggerService.warn(message, payload);
|
|
13004
|
+
console.error(message, payload);
|
|
13005
|
+
errorEmitter.next(error);
|
|
13006
|
+
},
|
|
13007
|
+
defaultValue: false,
|
|
13008
|
+
});
|
|
12864
13009
|
/**
|
|
12865
13010
|
* Emits signal tick results with correct execution context timestamp.
|
|
12866
13011
|
* Wraps emitter calls in ExecutionContextService.runInContext to preserve
|
|
@@ -13297,6 +13442,7 @@ class StrategyConnectionService {
|
|
|
13297
13442
|
onDispose: CREATE_COMMIT_DISPOSE_FN(this),
|
|
13298
13443
|
onCommit: CREATE_COMMIT_FN(this),
|
|
13299
13444
|
onSignalSync: CREATE_SYNC_FN(this, strategyName, exchangeName, frameName, backtest),
|
|
13445
|
+
onSignalPing: CREATE_SYNC_PENDING_FN(this, strategyName, exchangeName, frameName, backtest),
|
|
13300
13446
|
onHighestProfit: CREATE_HIGHEST_PROFIT_FN(this, strategyName, exchangeName, frameName, backtest),
|
|
13301
13447
|
onMaxDrawdown: CREATE_MAX_DRAWDOWN_FN(this, strategyName, exchangeName, frameName, backtest),
|
|
13302
13448
|
});
|
|
@@ -16231,6 +16377,22 @@ class ActionProxy {
|
|
|
16231
16377
|
await this._target.signalSync(event);
|
|
16232
16378
|
}
|
|
16233
16379
|
}
|
|
16380
|
+
/**
|
|
16381
|
+
* Gate for the pending-order ping (order still open on exchange?).
|
|
16382
|
+
* NOT wrapped in trycatch — exceptions propagate to CREATE_SYNC_PENDING_FN.
|
|
16383
|
+
*
|
|
16384
|
+
* @param event - Pending-ping event with action "signal-ping"
|
|
16385
|
+
*/
|
|
16386
|
+
async orderPing(event) {
|
|
16387
|
+
if (this._target.orderPing) {
|
|
16388
|
+
console.error("Action::orderPing is unwanted cause exchange integration should be implemented in Broker.useBrokerAdapter as an infrastructure domain layer");
|
|
16389
|
+
console.error("If you need to check whether the order is still open on the exchange, please use Broker.useBrokerAdapter with onOrderPing");
|
|
16390
|
+
console.error("If Action::orderPing throws the framework will close the position with closeReason \"closed\"!");
|
|
16391
|
+
console.error("");
|
|
16392
|
+
console.error("You have been warned!");
|
|
16393
|
+
await this._target.orderPing(event);
|
|
16394
|
+
}
|
|
16395
|
+
}
|
|
16234
16396
|
/**
|
|
16235
16397
|
* Cleans up resources with error capture.
|
|
16236
16398
|
*
|
|
@@ -16450,6 +16612,15 @@ const CALL_SIGNAL_SYNC_CALLBACK_FN = async (self, event, strategyName, frameName
|
|
|
16450
16612
|
await self.params.callbacks.onSignalSync(event, self.params.actionName, strategyName, frameName, isBacktest);
|
|
16451
16613
|
}
|
|
16452
16614
|
};
|
|
16615
|
+
/**
|
|
16616
|
+
* Calls onOrderPing callback WITHOUT trycatch — exceptions must propagate
|
|
16617
|
+
* up to CREATE_SYNC_PENDING_FN in StrategyConnectionService (which returns false on error).
|
|
16618
|
+
*/
|
|
16619
|
+
const CALL_ORDER_PING_CALLBACK_FN = async (self, event, strategyName, frameName, isBacktest) => {
|
|
16620
|
+
if (self.params.callbacks?.onOrderPing) {
|
|
16621
|
+
await self.params.callbacks.onOrderPing(event, self.params.actionName, strategyName, frameName, isBacktest);
|
|
16622
|
+
}
|
|
16623
|
+
};
|
|
16453
16624
|
/** Wrapper to call onInit callback with error handling */
|
|
16454
16625
|
const CALL_INIT_CALLBACK_FN = trycatch(async (self, strategyName, frameName, backtest) => {
|
|
16455
16626
|
if (self.params.callbacks?.onInit) {
|
|
@@ -16828,6 +16999,25 @@ class ClientAction {
|
|
|
16828
16999
|
await CALL_SIGNAL_SYNC_CALLBACK_FN(this, event, this.params.strategyName, this.params.frameName, event.backtest);
|
|
16829
17000
|
}
|
|
16830
17001
|
;
|
|
17002
|
+
/**
|
|
17003
|
+
* Gate for the pending-order ping (order still open on exchange?).
|
|
17004
|
+
* NOT wrapped in trycatch — exceptions propagate to CREATE_SYNC_PENDING_FN.
|
|
17005
|
+
*/
|
|
17006
|
+
async orderPing(event) {
|
|
17007
|
+
this.params.logger.debug("ClientAction orderPing", {
|
|
17008
|
+
actionName: this.params.actionName,
|
|
17009
|
+
strategyName: this.params.strategyName,
|
|
17010
|
+
frameName: this.params.frameName,
|
|
17011
|
+
});
|
|
17012
|
+
if (!this._handlerInstance) {
|
|
17013
|
+
await this.waitForInit();
|
|
17014
|
+
}
|
|
17015
|
+
// Call handler method if defined — exceptions propagate
|
|
17016
|
+
await this._handlerInstance?.orderPing(event);
|
|
17017
|
+
// Call callback if defined — exceptions propagate
|
|
17018
|
+
await CALL_ORDER_PING_CALLBACK_FN(this, event, this.params.strategyName, this.params.frameName, event.backtest);
|
|
17019
|
+
}
|
|
17020
|
+
;
|
|
16831
17021
|
}
|
|
16832
17022
|
|
|
16833
17023
|
/**
|
|
@@ -17090,6 +17280,22 @@ class ActionConnectionService {
|
|
|
17090
17280
|
const action = this.getAction(context.actionName, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
17091
17281
|
await action.signalSync(event);
|
|
17092
17282
|
};
|
|
17283
|
+
/**
|
|
17284
|
+
* Routes orderPing event to appropriate ClientAction instance.
|
|
17285
|
+
* NOT wrapped in trycatch — exceptions propagate to CREATE_SYNC_PENDING_FN.
|
|
17286
|
+
*
|
|
17287
|
+
* @param event - Pending-ping event with action "signal-ping"
|
|
17288
|
+
* @param backtest - Whether running in backtest mode
|
|
17289
|
+
* @param context - Execution context
|
|
17290
|
+
*/
|
|
17291
|
+
this.orderPing = async (event, backtest, context) => {
|
|
17292
|
+
this.loggerService.log("actionConnectionService orderPing", {
|
|
17293
|
+
backtest,
|
|
17294
|
+
context,
|
|
17295
|
+
});
|
|
17296
|
+
const action = this.getAction(context.actionName, context.strategyName, context.exchangeName, context.frameName, backtest);
|
|
17297
|
+
await action.orderPing(event);
|
|
17298
|
+
};
|
|
17093
17299
|
/**
|
|
17094
17300
|
* Disposes the ClientAction instance for the given action name.
|
|
17095
17301
|
*
|
|
@@ -19314,6 +19520,24 @@ class ActionCoreService {
|
|
|
19314
19520
|
await this.actionConnectionService.signalSync(event, backtest, { actionName, ...context });
|
|
19315
19521
|
}
|
|
19316
19522
|
};
|
|
19523
|
+
/**
|
|
19524
|
+
* Gates the pending-order ping across all registered actions.
|
|
19525
|
+
* NOT wrapped in trycatch — exceptions propagate to CREATE_SYNC_PENDING_FN.
|
|
19526
|
+
*
|
|
19527
|
+
* @param backtest - Whether running in backtest mode
|
|
19528
|
+
* @param event - Pending-ping event with action "signal-ping"
|
|
19529
|
+
* @param context - Strategy execution context
|
|
19530
|
+
*/
|
|
19531
|
+
this.orderPing = async (backtest, event, context) => {
|
|
19532
|
+
this.loggerService.log("actionCoreService orderPing", {
|
|
19533
|
+
context,
|
|
19534
|
+
});
|
|
19535
|
+
await this.validate(context);
|
|
19536
|
+
const { actions = [] } = this.strategySchemaService.get(context.strategyName);
|
|
19537
|
+
for (const actionName of actions) {
|
|
19538
|
+
await this.actionConnectionService.orderPing(event, backtest, { actionName, ...context });
|
|
19539
|
+
}
|
|
19540
|
+
};
|
|
19317
19541
|
/**
|
|
19318
19542
|
* Disposes all ClientAction instances for the strategy.
|
|
19319
19543
|
*
|
|
@@ -19782,6 +20006,29 @@ const VALID_METHOD_NAMES = [
|
|
|
19782
20006
|
"riskRejection",
|
|
19783
20007
|
"dispose",
|
|
19784
20008
|
];
|
|
20009
|
+
/**
|
|
20010
|
+
* Exchange-integration handler methods that exist on IAction but are intentionally NOT in
|
|
20011
|
+
* VALID_METHOD_NAMES. They are discouraged on action handlers: exchange synchronization belongs
|
|
20012
|
+
* in the infrastructure domain layer (Broker.useBrokerAdapter), not in actions. Naming a handler
|
|
20013
|
+
* method one of these produces a dedicated error redirecting to the Broker adapter instead of the
|
|
20014
|
+
* generic "invalid method" suggestion.
|
|
20015
|
+
*/
|
|
20016
|
+
const DISCOURAGED_METHOD_NAMES = ["signalSync", "orderPing"];
|
|
20017
|
+
/**
|
|
20018
|
+
* Builds the dedicated error message for a discouraged exchange-integration handler method.
|
|
20019
|
+
*
|
|
20020
|
+
* @param actionName - Name of the action being validated
|
|
20021
|
+
* @param methodName - The discouraged method name found on the handler
|
|
20022
|
+
* @returns Multi-line error message redirecting to the Broker adapter
|
|
20023
|
+
*/
|
|
20024
|
+
const DISCOURAGED_METHOD_MESSAGE = (actionName, methodName) => str.newline([
|
|
20025
|
+
`ActionSchema ${actionName} contains discouraged method "${methodName}". `,
|
|
20026
|
+
`Exchange integration must be implemented in Broker.useBrokerAdapter as the infrastructure domain layer, not in an action handler.`,
|
|
20027
|
+
typo.nbsp,
|
|
20028
|
+
`Use Broker.useBrokerAdapter with onOrderPing (order still open?) and onSignalOpenCommit / onSignalCloseCommit (order fill) instead.`,
|
|
20029
|
+
typo.nbsp,
|
|
20030
|
+
`If you want to keep this property name use one of these patterns: _${methodName} or #${methodName}`,
|
|
20031
|
+
]);
|
|
19785
20032
|
/**
|
|
19786
20033
|
* Calculates the Levenshtein distance between two strings.
|
|
19787
20034
|
*
|
|
@@ -19884,6 +20131,13 @@ const VALIDATE_CLASS_METHODS = (actionName, handler, self) => {
|
|
|
19884
20131
|
}
|
|
19885
20132
|
const descriptor = Object.getOwnPropertyDescriptor(handler.prototype, methodName);
|
|
19886
20133
|
const isMethod = descriptor && typeof descriptor.value === "function";
|
|
20134
|
+
if (isMethod && DISCOURAGED_METHOD_NAMES.includes(methodName)) {
|
|
20135
|
+
const msg = DISCOURAGED_METHOD_MESSAGE(actionName, methodName);
|
|
20136
|
+
self.loggerService.log(`actionValidationService exception thrown`, {
|
|
20137
|
+
msg,
|
|
20138
|
+
});
|
|
20139
|
+
console.log(msg);
|
|
20140
|
+
}
|
|
19887
20141
|
if (isMethod && !VALID_METHOD_NAMES.includes(methodName)) {
|
|
19888
20142
|
const suggestions = FIND_SUGGESTIONS(methodName, VALID_METHOD_NAMES);
|
|
19889
20143
|
const lines = [
|
|
@@ -19923,6 +20177,14 @@ const VALIDATE_OBJECT_METHODS = (actionName, handler, self) => {
|
|
|
19923
20177
|
if (methodName.startsWith("_")) {
|
|
19924
20178
|
continue;
|
|
19925
20179
|
}
|
|
20180
|
+
if (typeof handler[methodName] === "function" &&
|
|
20181
|
+
DISCOURAGED_METHOD_NAMES.includes(methodName)) {
|
|
20182
|
+
const msg = DISCOURAGED_METHOD_MESSAGE(actionName, methodName);
|
|
20183
|
+
self.loggerService.log(`actionValidationService exception thrown`, {
|
|
20184
|
+
msg,
|
|
20185
|
+
});
|
|
20186
|
+
console.log(msg);
|
|
20187
|
+
}
|
|
19926
20188
|
if (typeof handler[methodName] === "function" &&
|
|
19927
20189
|
!VALID_METHOD_NAMES.includes(methodName)) {
|
|
19928
20190
|
const suggestions = FIND_SUGGESTIONS(methodName, VALID_METHOD_NAMES);
|
|
@@ -42141,6 +42403,7 @@ const breakevenNewTakeProfitPrice = (priceTakeProfit, trailingPriceTakeProfit) =
|
|
|
42141
42403
|
|
|
42142
42404
|
const BROKER_METHOD_NAME_COMMIT_SIGNAL_OPEN = "BrokerAdapter.commitSignalOpen";
|
|
42143
42405
|
const BROKER_METHOD_NAME_COMMIT_SIGNAL_CLOSE = "BrokerAdapter.commitSignalClose";
|
|
42406
|
+
const BROKER_METHOD_NAME_COMMIT_SIGNAL_PENDING = "BrokerAdapter.commitSignalPending";
|
|
42144
42407
|
const BROKER_METHOD_NAME_COMMIT_PARTIAL_PROFIT = "BrokerAdapter.commitPartialProfit";
|
|
42145
42408
|
const BROKER_METHOD_NAME_COMMIT_PARTIAL_LOSS = "BrokerAdapter.commitPartialLoss";
|
|
42146
42409
|
const BROKER_METHOD_NAME_COMMIT_TRAILING_STOP = "BrokerAdapter.commitTrailingStop";
|
|
@@ -42154,6 +42417,7 @@ const BROKER_METHOD_NAME_CLEAR = "BrokerAdapter.clear";
|
|
|
42154
42417
|
const BROKER_BASE_METHOD_NAME_WAIT_FOR_INIT = "BrokerBase.waitForInit";
|
|
42155
42418
|
const BROKER_BASE_METHOD_NAME_ON_SIGNAL_OPEN = "BrokerBase.onSignalOpenCommit";
|
|
42156
42419
|
const BROKER_BASE_METHOD_NAME_ON_SIGNAL_CLOSE = "BrokerBase.onSignalCloseCommit";
|
|
42420
|
+
const BROKER_BASE_METHOD_NAME_ON_SIGNAL_PENDING = "BrokerBase.onOrderPing";
|
|
42157
42421
|
const BROKER_BASE_METHOD_NAME_ON_PARTIAL_PROFIT = "BrokerBase.onPartialProfitCommit";
|
|
42158
42422
|
const BROKER_BASE_METHOD_NAME_ON_PARTIAL_LOSS = "BrokerBase.onPartialLossCommit";
|
|
42159
42423
|
const BROKER_BASE_METHOD_NAME_ON_TRAILING_STOP = "BrokerBase.onTrailingStopCommit";
|
|
@@ -42202,6 +42466,25 @@ class BrokerProxy {
|
|
|
42202
42466
|
}
|
|
42203
42467
|
throw new Error("BrokerProxy onSignalOpenCommit is not implemented");
|
|
42204
42468
|
}
|
|
42469
|
+
/**
|
|
42470
|
+
* Forwards a pending-order ping to the underlying adapter.
|
|
42471
|
+
*
|
|
42472
|
+
* If the adapter does not implement `onOrderPing`, the call is silently skipped
|
|
42473
|
+
* (the order is assumed still open). When implemented, exceptions propagate — a throw means
|
|
42474
|
+
* the order was NOT FOUND by `payload.signalId` and the framework closes the position with
|
|
42475
|
+
* closeReason "closed". The adapter must throw ONLY on a confirmed "order not found by id"
|
|
42476
|
+
* result and SWALLOW transient/network errors (return normally), otherwise a connectivity blip
|
|
42477
|
+
* would wrongly close an open position.
|
|
42478
|
+
*
|
|
42479
|
+
* @param payload - Pending ping details: symbol, signalId, position, prices, pnl, context, backtest flag.
|
|
42480
|
+
*/
|
|
42481
|
+
async onOrderPing(payload) {
|
|
42482
|
+
if (this._instance.onOrderPing) {
|
|
42483
|
+
await this.waitForInit();
|
|
42484
|
+
await this._instance.onOrderPing(payload);
|
|
42485
|
+
return;
|
|
42486
|
+
}
|
|
42487
|
+
}
|
|
42205
42488
|
/**
|
|
42206
42489
|
* Forwards a signal-close event to the underlying adapter.
|
|
42207
42490
|
* Throws if the adapter does not implement `onSignalCloseCommit`.
|
|
@@ -42431,6 +42714,32 @@ class BrokerAdapter {
|
|
|
42431
42714
|
await instance.onSignalCloseCommit(payload);
|
|
42432
42715
|
}
|
|
42433
42716
|
};
|
|
42717
|
+
/**
|
|
42718
|
+
* Forwards a pending-order ping to the registered broker adapter.
|
|
42719
|
+
*
|
|
42720
|
+
* Called automatically via syncPendingSubject when `enable()` is active, on every live tick
|
|
42721
|
+
* while a pending signal is monitored. Skipped silently in backtest mode or when no adapter is
|
|
42722
|
+
* registered. Exceptions are NOT swallowed: a throw from the adapter propagates up to
|
|
42723
|
+
* syncPendingSubject.next() → CREATE_SYNC_PENDING_FN, which closes the position with "closed".
|
|
42724
|
+
*
|
|
42725
|
+
* @param payload - Pending ping details: symbol, position, prices, pnl, context, backtest flag
|
|
42726
|
+
*/
|
|
42727
|
+
this.commitSignalPending = async (payload) => {
|
|
42728
|
+
bt.loggerService.info(BROKER_METHOD_NAME_COMMIT_SIGNAL_PENDING, {
|
|
42729
|
+
symbol: payload.symbol,
|
|
42730
|
+
context: payload.context,
|
|
42731
|
+
});
|
|
42732
|
+
if (!this.enable.hasValue()) {
|
|
42733
|
+
return;
|
|
42734
|
+
}
|
|
42735
|
+
if (payload.backtest) {
|
|
42736
|
+
return;
|
|
42737
|
+
}
|
|
42738
|
+
const instance = this.getInstance();
|
|
42739
|
+
if (instance) {
|
|
42740
|
+
await instance.onOrderPing(payload);
|
|
42741
|
+
}
|
|
42742
|
+
};
|
|
42434
42743
|
/**
|
|
42435
42744
|
* Intercepts a partial-profit close before DI-core mutation.
|
|
42436
42745
|
*
|
|
@@ -42733,6 +43042,7 @@ class BrokerAdapter {
|
|
|
42733
43042
|
position: event.signal.position,
|
|
42734
43043
|
cost: event.signal.cost,
|
|
42735
43044
|
symbol: event.symbol,
|
|
43045
|
+
signalId: event.signalId,
|
|
42736
43046
|
priceTakeProfit: event.signal.priceTakeProfit,
|
|
42737
43047
|
priceStopLoss: event.signal.priceStopLoss,
|
|
42738
43048
|
priceOpen: event.signal.priceOpen,
|
|
@@ -42756,6 +43066,7 @@ class BrokerAdapter {
|
|
|
42756
43066
|
currentPrice: event.currentPrice,
|
|
42757
43067
|
cost: event.signal.cost,
|
|
42758
43068
|
symbol: event.symbol,
|
|
43069
|
+
signalId: event.signalId,
|
|
42759
43070
|
pnl: event.signal.pnl,
|
|
42760
43071
|
priceOpen: event.signal.priceOpen,
|
|
42761
43072
|
peakProfit: event.signal.peakProfit,
|
|
@@ -42772,7 +43083,29 @@ class BrokerAdapter {
|
|
|
42772
43083
|
backtest: event.backtest,
|
|
42773
43084
|
});
|
|
42774
43085
|
});
|
|
42775
|
-
const
|
|
43086
|
+
const unSignalPending = syncPendingSubject.subscribe(async (event) => {
|
|
43087
|
+
await this.commitSignalPending({
|
|
43088
|
+
position: event.position,
|
|
43089
|
+
currentPrice: event.currentPrice,
|
|
43090
|
+
symbol: event.symbol,
|
|
43091
|
+
signalId: event.signalId,
|
|
43092
|
+
priceOpen: event.priceOpen,
|
|
43093
|
+
priceTakeProfit: event.priceTakeProfit,
|
|
43094
|
+
priceStopLoss: event.priceStopLoss,
|
|
43095
|
+
pnl: event.pnl,
|
|
43096
|
+
peakProfit: event.peakProfit,
|
|
43097
|
+
maxDrawdown: event.maxDrawdown,
|
|
43098
|
+
totalEntries: event.totalEntries,
|
|
43099
|
+
totalPartials: event.totalPartials,
|
|
43100
|
+
context: {
|
|
43101
|
+
strategyName: event.strategyName,
|
|
43102
|
+
exchangeName: event.exchangeName,
|
|
43103
|
+
frameName: event.frameName,
|
|
43104
|
+
},
|
|
43105
|
+
backtest: event.backtest,
|
|
43106
|
+
});
|
|
43107
|
+
});
|
|
43108
|
+
const disposeFn = compose(() => unSignalOpen(), () => unSignalClose(), () => unSignalPending());
|
|
42776
43109
|
return () => {
|
|
42777
43110
|
this.enable.clear();
|
|
42778
43111
|
disposeFn();
|
|
@@ -42945,6 +43278,44 @@ class BrokerBase {
|
|
|
42945
43278
|
context: payload.context,
|
|
42946
43279
|
});
|
|
42947
43280
|
}
|
|
43281
|
+
/**
|
|
43282
|
+
* Called on every live tick while a pending signal is monitored, BEFORE TP/SL/time evaluation.
|
|
43283
|
+
*
|
|
43284
|
+
* Override to query the exchange for the order by `payload.signalId` and THROW ONLY when it is
|
|
43285
|
+
* definitively NOT FOUND by that id (filled, cancelled, or liquidated externally) — the framework
|
|
43286
|
+
* then closes the position with closeReason "closed". The default implementation logs and returns
|
|
43287
|
+
* normally, which keeps the position under normal TP/SL monitoring.
|
|
43288
|
+
*
|
|
43289
|
+
* CRITICAL: swallow transient/network errors (timeout, 5xx, rate limit, disconnect) — return
|
|
43290
|
+
* normally instead of throwing. A thrown network error would wrongly close an open position; only
|
|
43291
|
+
* a confirmed "order not found by id" response is a valid reason to throw.
|
|
43292
|
+
*
|
|
43293
|
+
* @param payload - Pending ping details: symbol, signalId, position, prices, pnl, context, backtest
|
|
43294
|
+
*
|
|
43295
|
+
* @example
|
|
43296
|
+
* ```typescript
|
|
43297
|
+
* async onOrderPing(payload: BrokerSignalPendingPayload) {
|
|
43298
|
+
* super.onOrderPing(payload); // Keep parent logging
|
|
43299
|
+
* let order: Order | null;
|
|
43300
|
+
* try {
|
|
43301
|
+
* order = await this.exchange.getOrderById(payload.signalId);
|
|
43302
|
+
* } catch (networkError) {
|
|
43303
|
+
* // Transient/network error — swallow and keep the position open, retry next tick
|
|
43304
|
+
* return;
|
|
43305
|
+
* }
|
|
43306
|
+
* if (!order) {
|
|
43307
|
+
* // Confirmed not found by id — close the position
|
|
43308
|
+
* throw new Error(`Order ${payload.signalId} not found on the exchange`);
|
|
43309
|
+
* }
|
|
43310
|
+
* }
|
|
43311
|
+
* ```
|
|
43312
|
+
*/
|
|
43313
|
+
async onOrderPing(payload) {
|
|
43314
|
+
bt.loggerService.info(BROKER_BASE_METHOD_NAME_ON_SIGNAL_PENDING, {
|
|
43315
|
+
symbol: payload.symbol,
|
|
43316
|
+
context: payload.context,
|
|
43317
|
+
});
|
|
43318
|
+
}
|
|
42948
43319
|
/**
|
|
42949
43320
|
* Called when a position is fully closed (SL/TP hit or manual close).
|
|
42950
43321
|
*
|
|
@@ -43343,6 +43714,7 @@ async function commitPartialProfit(symbol, percentToClose) {
|
|
|
43343
43714
|
}
|
|
43344
43715
|
await Broker.commitPartialProfit({
|
|
43345
43716
|
symbol,
|
|
43717
|
+
signalId: signalForProfit.id,
|
|
43346
43718
|
percentToClose,
|
|
43347
43719
|
cost: percentToCloseCost(percentToClose, investedCostForProfit),
|
|
43348
43720
|
currentPrice,
|
|
@@ -43408,6 +43780,7 @@ async function commitPartialLoss(symbol, percentToClose) {
|
|
|
43408
43780
|
}
|
|
43409
43781
|
await Broker.commitPartialLoss({
|
|
43410
43782
|
symbol,
|
|
43783
|
+
signalId: signalForLoss.id,
|
|
43411
43784
|
percentToClose,
|
|
43412
43785
|
cost: percentToCloseCost(percentToClose, investedCostForLoss),
|
|
43413
43786
|
currentPrice,
|
|
@@ -43489,6 +43862,7 @@ async function commitTrailingStop(symbol, percentShift, currentPrice) {
|
|
|
43489
43862
|
}
|
|
43490
43863
|
await Broker.commitTrailingStop({
|
|
43491
43864
|
symbol,
|
|
43865
|
+
signalId: signal.id,
|
|
43492
43866
|
percentShift,
|
|
43493
43867
|
currentPrice,
|
|
43494
43868
|
newStopLossPrice: slPercentShiftToPrice(percentShift, signal.priceStopLoss, effectivePriceOpen, signal.position),
|
|
@@ -43569,6 +43943,7 @@ async function commitTrailingTake(symbol, percentShift, currentPrice) {
|
|
|
43569
43943
|
}
|
|
43570
43944
|
await Broker.commitTrailingTake({
|
|
43571
43945
|
symbol,
|
|
43946
|
+
signalId: signal.id,
|
|
43572
43947
|
percentShift,
|
|
43573
43948
|
currentPrice,
|
|
43574
43949
|
newTakeProfitPrice: tpPercentShiftToPrice(percentShift, signal.priceTakeProfit, effectivePriceOpen, signal.position),
|
|
@@ -43620,6 +43995,7 @@ async function commitTrailingStopCost(symbol, newStopLossPrice) {
|
|
|
43620
43995
|
}
|
|
43621
43996
|
await Broker.commitTrailingStop({
|
|
43622
43997
|
symbol,
|
|
43998
|
+
signalId: signal.id,
|
|
43623
43999
|
percentShift,
|
|
43624
44000
|
currentPrice,
|
|
43625
44001
|
newStopLossPrice,
|
|
@@ -43671,6 +44047,7 @@ async function commitTrailingTakeCost(symbol, newTakeProfitPrice) {
|
|
|
43671
44047
|
}
|
|
43672
44048
|
await Broker.commitTrailingTake({
|
|
43673
44049
|
symbol,
|
|
44050
|
+
signalId: signal.id,
|
|
43674
44051
|
percentShift,
|
|
43675
44052
|
currentPrice,
|
|
43676
44053
|
newTakeProfitPrice,
|
|
@@ -43732,6 +44109,7 @@ async function commitBreakeven(symbol) {
|
|
|
43732
44109
|
}
|
|
43733
44110
|
await Broker.commitBreakeven({
|
|
43734
44111
|
symbol,
|
|
44112
|
+
signalId: signal.id,
|
|
43735
44113
|
currentPrice,
|
|
43736
44114
|
newStopLossPrice: breakevenNewStopLossPrice(effectivePriceOpen),
|
|
43737
44115
|
newTakeProfitPrice: breakevenNewTakeProfitPrice(signal.priceTakeProfit, signal._trailingPriceTakeProfit),
|
|
@@ -43822,6 +44200,7 @@ async function commitAverageBuy(symbol, cost = GLOBAL_CONFIG.CC_POSITION_ENTRY_C
|
|
|
43822
44200
|
}
|
|
43823
44201
|
await Broker.commitAverageBuy({
|
|
43824
44202
|
symbol,
|
|
44203
|
+
signalId: signalForAvgBuy.id,
|
|
43825
44204
|
currentPrice,
|
|
43826
44205
|
cost,
|
|
43827
44206
|
position: signalForAvgBuy.position,
|
|
@@ -44205,6 +44584,7 @@ async function commitPartialProfitCost(symbol, dollarAmount) {
|
|
|
44205
44584
|
}
|
|
44206
44585
|
await Broker.commitPartialProfit({
|
|
44207
44586
|
symbol,
|
|
44587
|
+
signalId: signalForProfitCost.id,
|
|
44208
44588
|
percentToClose,
|
|
44209
44589
|
cost: dollarAmount,
|
|
44210
44590
|
currentPrice,
|
|
@@ -44273,6 +44653,7 @@ async function commitPartialLossCost(symbol, dollarAmount) {
|
|
|
44273
44653
|
}
|
|
44274
44654
|
await Broker.commitPartialLoss({
|
|
44275
44655
|
symbol,
|
|
44656
|
+
signalId: signalForLossCost.id,
|
|
44276
44657
|
percentToClose,
|
|
44277
44658
|
cost: dollarAmount,
|
|
44278
44659
|
currentPrice,
|
|
@@ -48827,6 +49208,7 @@ class BacktestUtils {
|
|
|
48827
49208
|
}
|
|
48828
49209
|
await Broker.commitPartialProfit({
|
|
48829
49210
|
symbol,
|
|
49211
|
+
signalId: signalForProfit.id,
|
|
48830
49212
|
percentToClose,
|
|
48831
49213
|
cost: percentToCloseCost(percentToClose, investedCostForProfit),
|
|
48832
49214
|
currentPrice,
|
|
@@ -48898,6 +49280,7 @@ class BacktestUtils {
|
|
|
48898
49280
|
}
|
|
48899
49281
|
await Broker.commitPartialLoss({
|
|
48900
49282
|
symbol,
|
|
49283
|
+
signalId: signalForLoss.id,
|
|
48901
49284
|
percentToClose,
|
|
48902
49285
|
cost: percentToCloseCost(percentToClose, investedCostForLoss),
|
|
48903
49286
|
currentPrice,
|
|
@@ -48971,6 +49354,7 @@ class BacktestUtils {
|
|
|
48971
49354
|
}
|
|
48972
49355
|
await Broker.commitPartialProfit({
|
|
48973
49356
|
symbol,
|
|
49357
|
+
signalId: signalForProfitCost.id,
|
|
48974
49358
|
percentToClose,
|
|
48975
49359
|
cost: dollarAmount,
|
|
48976
49360
|
currentPrice,
|
|
@@ -49044,6 +49428,7 @@ class BacktestUtils {
|
|
|
49044
49428
|
}
|
|
49045
49429
|
await Broker.commitPartialLoss({
|
|
49046
49430
|
symbol,
|
|
49431
|
+
signalId: signalForLossCost.id,
|
|
49047
49432
|
percentToClose,
|
|
49048
49433
|
cost: dollarAmount,
|
|
49049
49434
|
currentPrice,
|
|
@@ -49130,6 +49515,7 @@ class BacktestUtils {
|
|
|
49130
49515
|
}
|
|
49131
49516
|
await Broker.commitTrailingStop({
|
|
49132
49517
|
symbol,
|
|
49518
|
+
signalId: signal.id,
|
|
49133
49519
|
percentShift,
|
|
49134
49520
|
currentPrice,
|
|
49135
49521
|
newStopLossPrice: slPercentShiftToPrice(percentShift, signal.priceStopLoss, effectivePriceOpen, signal.position),
|
|
@@ -49215,6 +49601,7 @@ class BacktestUtils {
|
|
|
49215
49601
|
}
|
|
49216
49602
|
await Broker.commitTrailingTake({
|
|
49217
49603
|
symbol,
|
|
49604
|
+
signalId: signal.id,
|
|
49218
49605
|
percentShift,
|
|
49219
49606
|
currentPrice,
|
|
49220
49607
|
newTakeProfitPrice: tpPercentShiftToPrice(percentShift, signal.priceTakeProfit, effectivePriceOpen, signal.position),
|
|
@@ -49269,6 +49656,7 @@ class BacktestUtils {
|
|
|
49269
49656
|
}
|
|
49270
49657
|
await Broker.commitTrailingStop({
|
|
49271
49658
|
symbol,
|
|
49659
|
+
signalId: signal.id,
|
|
49272
49660
|
percentShift,
|
|
49273
49661
|
currentPrice,
|
|
49274
49662
|
newStopLossPrice,
|
|
@@ -49323,6 +49711,7 @@ class BacktestUtils {
|
|
|
49323
49711
|
}
|
|
49324
49712
|
await Broker.commitTrailingTake({
|
|
49325
49713
|
symbol,
|
|
49714
|
+
signalId: signal.id,
|
|
49326
49715
|
percentShift,
|
|
49327
49716
|
currentPrice,
|
|
49328
49717
|
newTakeProfitPrice,
|
|
@@ -49384,6 +49773,7 @@ class BacktestUtils {
|
|
|
49384
49773
|
}
|
|
49385
49774
|
await Broker.commitBreakeven({
|
|
49386
49775
|
symbol,
|
|
49776
|
+
signalId: signal.id,
|
|
49387
49777
|
currentPrice,
|
|
49388
49778
|
newStopLossPrice: breakevenNewStopLossPrice(effectivePriceOpen),
|
|
49389
49779
|
newTakeProfitPrice: breakevenNewTakeProfitPrice(signal.priceTakeProfit, signal._trailingPriceTakeProfit),
|
|
@@ -49483,6 +49873,7 @@ class BacktestUtils {
|
|
|
49483
49873
|
}
|
|
49484
49874
|
await Broker.commitAverageBuy({
|
|
49485
49875
|
symbol,
|
|
49876
|
+
signalId: signalForAvgBuy.id,
|
|
49486
49877
|
currentPrice,
|
|
49487
49878
|
cost,
|
|
49488
49879
|
position: signalForAvgBuy.position,
|
|
@@ -51730,6 +52121,7 @@ class LiveUtils {
|
|
|
51730
52121
|
}
|
|
51731
52122
|
await Broker.commitPartialProfit({
|
|
51732
52123
|
symbol,
|
|
52124
|
+
signalId: signalForProfit.id,
|
|
51733
52125
|
percentToClose,
|
|
51734
52126
|
cost: percentToCloseCost(percentToClose, investedCost),
|
|
51735
52127
|
currentPrice,
|
|
@@ -51820,6 +52212,7 @@ class LiveUtils {
|
|
|
51820
52212
|
}
|
|
51821
52213
|
await Broker.commitPartialLoss({
|
|
51822
52214
|
symbol,
|
|
52215
|
+
signalId: signalForLoss.id,
|
|
51823
52216
|
percentToClose,
|
|
51824
52217
|
cost: percentToCloseCost(percentToClose, investedCost),
|
|
51825
52218
|
currentPrice,
|
|
@@ -51912,6 +52305,7 @@ class LiveUtils {
|
|
|
51912
52305
|
}
|
|
51913
52306
|
await Broker.commitPartialProfit({
|
|
51914
52307
|
symbol,
|
|
52308
|
+
signalId: signalForProfitCost.id,
|
|
51915
52309
|
percentToClose,
|
|
51916
52310
|
cost: dollarAmount,
|
|
51917
52311
|
currentPrice,
|
|
@@ -52004,6 +52398,7 @@ class LiveUtils {
|
|
|
52004
52398
|
}
|
|
52005
52399
|
await Broker.commitPartialLoss({
|
|
52006
52400
|
symbol,
|
|
52401
|
+
signalId: signalForLossCost.id,
|
|
52007
52402
|
percentToClose,
|
|
52008
52403
|
cost: dollarAmount,
|
|
52009
52404
|
currentPrice,
|
|
@@ -52109,6 +52504,7 @@ class LiveUtils {
|
|
|
52109
52504
|
}
|
|
52110
52505
|
await Broker.commitTrailingStop({
|
|
52111
52506
|
symbol,
|
|
52507
|
+
signalId: signal.id,
|
|
52112
52508
|
percentShift,
|
|
52113
52509
|
currentPrice,
|
|
52114
52510
|
newStopLossPrice: slPercentShiftToPrice(percentShift, signal.priceStopLoss, effectivePriceOpen, signal.position),
|
|
@@ -52209,6 +52605,7 @@ class LiveUtils {
|
|
|
52209
52605
|
}
|
|
52210
52606
|
await Broker.commitTrailingTake({
|
|
52211
52607
|
symbol,
|
|
52608
|
+
signalId: signal.id,
|
|
52212
52609
|
percentShift,
|
|
52213
52610
|
currentPrice,
|
|
52214
52611
|
newTakeProfitPrice: tpPercentShiftToPrice(percentShift, signal.priceTakeProfit, effectivePriceOpen, signal.position),
|
|
@@ -52279,6 +52676,7 @@ class LiveUtils {
|
|
|
52279
52676
|
}
|
|
52280
52677
|
await Broker.commitTrailingStop({
|
|
52281
52678
|
symbol,
|
|
52679
|
+
signalId: signal.id,
|
|
52282
52680
|
percentShift,
|
|
52283
52681
|
currentPrice,
|
|
52284
52682
|
newStopLossPrice,
|
|
@@ -52349,6 +52747,7 @@ class LiveUtils {
|
|
|
52349
52747
|
}
|
|
52350
52748
|
await Broker.commitTrailingTake({
|
|
52351
52749
|
symbol,
|
|
52750
|
+
signalId: signal.id,
|
|
52352
52751
|
percentShift,
|
|
52353
52752
|
currentPrice,
|
|
52354
52753
|
newTakeProfitPrice,
|
|
@@ -52426,6 +52825,7 @@ class LiveUtils {
|
|
|
52426
52825
|
}
|
|
52427
52826
|
await Broker.commitBreakeven({
|
|
52428
52827
|
symbol,
|
|
52828
|
+
signalId: signal.id,
|
|
52429
52829
|
currentPrice,
|
|
52430
52830
|
newStopLossPrice: breakevenNewStopLossPrice(effectivePriceOpen),
|
|
52431
52831
|
newTakeProfitPrice: breakevenNewTakeProfitPrice(signal.priceTakeProfit, signal._trailingPriceTakeProfit),
|
|
@@ -52543,6 +52943,7 @@ class LiveUtils {
|
|
|
52543
52943
|
}
|
|
52544
52944
|
await Broker.commitAverageBuy({
|
|
52545
52945
|
symbol,
|
|
52946
|
+
signalId: signalForAvgBuy.id,
|
|
52546
52947
|
currentPrice,
|
|
52547
52948
|
cost,
|
|
52548
52949
|
position: signalForAvgBuy.position,
|
|
@@ -59964,6 +60365,7 @@ const SUBJECT_ISOLATION_LIST = [
|
|
|
59964
60365
|
signalLiveEmitter,
|
|
59965
60366
|
strategyCommitSubject,
|
|
59966
60367
|
syncSubject,
|
|
60368
|
+
syncPendingSubject,
|
|
59967
60369
|
validationSubject,
|
|
59968
60370
|
signalNotifySubject,
|
|
59969
60371
|
beforeStartSubject,
|