backtest-kit 4.0.2 → 5.0.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 +442 -25
- package/build/index.mjs +441 -26
- package/package.json +1 -1
- package/types.d.ts +271 -11
package/build/index.mjs
CHANGED
|
@@ -450,9 +450,17 @@ const GLOBAL_CONFIG = {
|
|
|
450
450
|
* Allows to commitAverageBuy if currentPrice is not the lowest price since entry, but still lower than priceOpen.
|
|
451
451
|
* This can help improve average entry price in cases where price has rebounded after entry but is still below priceOpen, without waiting for a new lower price.
|
|
452
452
|
*
|
|
453
|
-
* Default:
|
|
453
|
+
* Default: false (DCA logic enabled only when antirecord is broken)
|
|
454
454
|
*/
|
|
455
455
|
CC_ENABLE_DCA_EVERYWHERE: false,
|
|
456
|
+
/**
|
|
457
|
+
* Enables PPPL (Partial Profit, Partial Loss) logic even if this breaks a direction of exits
|
|
458
|
+
* Allows to take partial profit or loss on a position even if it results in a mix of profit and loss exits
|
|
459
|
+
* This can help lock in profits or cut losses on part of the position without waiting for a perfect exit scenario.
|
|
460
|
+
*
|
|
461
|
+
* Default: false (PPPL logic is only applied when it does not break the direction of exits, ensuring clearer profit/loss outcomes)
|
|
462
|
+
*/
|
|
463
|
+
CC_ENABLE_PPPL_EVERYWHERE: false,
|
|
456
464
|
/**
|
|
457
465
|
* Cost of entering a position (in USD).
|
|
458
466
|
* This is used as a default value for calculating position size and risk management when cost data is not provided by the strategy
|
|
@@ -7428,10 +7436,12 @@ class ClientStrategy {
|
|
|
7428
7436
|
if (typeof currentPrice !== "number" || !isFinite(currentPrice) || currentPrice <= 0)
|
|
7429
7437
|
return false;
|
|
7430
7438
|
const effectivePriceOpen = getEffectivePriceOpen(this._pendingSignal);
|
|
7431
|
-
if (
|
|
7432
|
-
|
|
7433
|
-
|
|
7434
|
-
|
|
7439
|
+
if (!GLOBAL_CONFIG.CC_ENABLE_PPPL_EVERYWHERE) {
|
|
7440
|
+
if (this._pendingSignal.position === "long" && currentPrice <= effectivePriceOpen)
|
|
7441
|
+
return false;
|
|
7442
|
+
if (this._pendingSignal.position === "short" && currentPrice >= effectivePriceOpen)
|
|
7443
|
+
return false;
|
|
7444
|
+
}
|
|
7435
7445
|
const effectiveTakeProfit = this._pendingSignal._trailingPriceTakeProfit ?? this._pendingSignal.priceTakeProfit;
|
|
7436
7446
|
if (this._pendingSignal.position === "long" && currentPrice >= effectiveTakeProfit)
|
|
7437
7447
|
return false;
|
|
@@ -7515,7 +7525,7 @@ class ClientStrategy {
|
|
|
7515
7525
|
throw new Error(`ClientStrategy partialProfit: currentPrice must be a positive finite number, got ${currentPrice}`);
|
|
7516
7526
|
}
|
|
7517
7527
|
// Validation: currentPrice must be moving toward TP (profit direction)
|
|
7518
|
-
{
|
|
7528
|
+
if (!GLOBAL_CONFIG.CC_ENABLE_PPPL_EVERYWHERE) {
|
|
7519
7529
|
const effectivePriceOpen = getEffectivePriceOpen(this._pendingSignal);
|
|
7520
7530
|
if (this._pendingSignal.position === "long") {
|
|
7521
7531
|
// For LONG: currentPrice must be higher than effectivePriceOpen (moving toward TP)
|
|
@@ -7609,10 +7619,12 @@ class ClientStrategy {
|
|
|
7609
7619
|
if (typeof currentPrice !== "number" || !isFinite(currentPrice) || currentPrice <= 0)
|
|
7610
7620
|
return false;
|
|
7611
7621
|
const effectivePriceOpen = getEffectivePriceOpen(this._pendingSignal);
|
|
7612
|
-
if (
|
|
7613
|
-
|
|
7614
|
-
|
|
7615
|
-
|
|
7622
|
+
if (!GLOBAL_CONFIG.CC_ENABLE_PPPL_EVERYWHERE) {
|
|
7623
|
+
if (this._pendingSignal.position === "long" && currentPrice >= effectivePriceOpen)
|
|
7624
|
+
return false;
|
|
7625
|
+
if (this._pendingSignal.position === "short" && currentPrice <= effectivePriceOpen)
|
|
7626
|
+
return false;
|
|
7627
|
+
}
|
|
7616
7628
|
const effectiveStopLoss = this._pendingSignal._trailingPriceStopLoss ?? this._pendingSignal.priceStopLoss;
|
|
7617
7629
|
if (this._pendingSignal.position === "long" && currentPrice <= effectiveStopLoss)
|
|
7618
7630
|
return false;
|
|
@@ -7696,7 +7708,7 @@ class ClientStrategy {
|
|
|
7696
7708
|
throw new Error(`ClientStrategy partialLoss: currentPrice must be a positive finite number, got ${currentPrice}`);
|
|
7697
7709
|
}
|
|
7698
7710
|
// Validation: currentPrice must be moving toward SL (loss direction)
|
|
7699
|
-
{
|
|
7711
|
+
if (!GLOBAL_CONFIG.CC_ENABLE_PPPL_EVERYWHERE) {
|
|
7700
7712
|
const effectivePriceOpen = getEffectivePriceOpen(this._pendingSignal);
|
|
7701
7713
|
if (this._pendingSignal.position === "long") {
|
|
7702
7714
|
// For LONG: currentPrice must be lower than effectivePriceOpen (moving toward SL)
|
|
@@ -10844,7 +10856,6 @@ const METHOD_NAME_PARTIAL_LOSS_AVAILABLE = "ActionBase.partialLossAvailable";
|
|
|
10844
10856
|
const METHOD_NAME_PING_SCHEDULED = "ActionBase.pingScheduled";
|
|
10845
10857
|
const METHOD_NAME_PING_ACTIVE = "ActionBase.pingActive";
|
|
10846
10858
|
const METHOD_NAME_RISK_REJECTION = "ActionBase.riskRejection";
|
|
10847
|
-
const METHOD_NAME_SIGNAL_SYNC = "ActionBase.signalSync";
|
|
10848
10859
|
const METHOD_NAME_DISPOSE = "ActionBase.dispose";
|
|
10849
10860
|
const DEFAULT_SOURCE = "default";
|
|
10850
10861
|
/**
|
|
@@ -11256,6 +11267,11 @@ class ActionProxy {
|
|
|
11256
11267
|
*/
|
|
11257
11268
|
async signalSync(event) {
|
|
11258
11269
|
if (this._target.signalSync) {
|
|
11270
|
+
console.error("Action::signalSync is unwanted cause exchange integration should be implemented in Broker.useBrokerAdapter as an infrastructure domain layer");
|
|
11271
|
+
console.error("If you need to implement custom logic on signal open/close, please use signal(), signalBacktest(), signalLive()");
|
|
11272
|
+
console.error("If Action::signalSync throws the exchange will not execute the order!");
|
|
11273
|
+
console.error("");
|
|
11274
|
+
console.error("You have been warned!");
|
|
11259
11275
|
await this._target.signalSync(event);
|
|
11260
11276
|
}
|
|
11261
11277
|
}
|
|
@@ -11718,19 +11734,6 @@ class ActionBase {
|
|
|
11718
11734
|
source,
|
|
11719
11735
|
});
|
|
11720
11736
|
}
|
|
11721
|
-
/**
|
|
11722
|
-
* Gate for position open/close via limit order. Default allows all.
|
|
11723
|
-
* Throw to reject — framework retries next tick.
|
|
11724
|
-
*
|
|
11725
|
-
* NOTE: Exceptions are NOT swallowed — they propagate to CREATE_SYNC_FN.
|
|
11726
|
-
*
|
|
11727
|
-
* @param event - Sync event with action "signal-open" or "signal-close"
|
|
11728
|
-
*/
|
|
11729
|
-
signalSync(_event, source = DEFAULT_SOURCE) {
|
|
11730
|
-
bt.loggerService.info(METHOD_NAME_SIGNAL_SYNC, {
|
|
11731
|
-
source,
|
|
11732
|
-
});
|
|
11733
|
-
}
|
|
11734
11737
|
/**
|
|
11735
11738
|
* Cleans up resources and subscriptions when action handler is disposed.
|
|
11736
11739
|
*
|
|
@@ -31761,6 +31764,11 @@ BrokerBase = makeExtendable(BrokerBase);
|
|
|
31761
31764
|
*/
|
|
31762
31765
|
const Broker = new BrokerAdapter();
|
|
31763
31766
|
|
|
31767
|
+
const POSITION_OVERLAP_LADDER_DEFAULT = {
|
|
31768
|
+
upperPercent: 1.5,
|
|
31769
|
+
lowerPercent: 1.5,
|
|
31770
|
+
};
|
|
31771
|
+
|
|
31764
31772
|
const CANCEL_SCHEDULED_METHOD_NAME = "strategy.commitCancelScheduled";
|
|
31765
31773
|
const CLOSE_PENDING_METHOD_NAME = "strategy.commitClosePending";
|
|
31766
31774
|
const PARTIAL_PROFIT_METHOD_NAME = "strategy.commitPartialProfit";
|
|
@@ -31786,6 +31794,8 @@ const GET_POSITION_PNL_PERCENT_METHOD_NAME = "strategy.getPositionPnlPercent";
|
|
|
31786
31794
|
const GET_POSITION_PNL_COST_METHOD_NAME = "strategy.getPositionPnlCost";
|
|
31787
31795
|
const GET_POSITION_LEVELS_METHOD_NAME = "strategy.getPositionLevels";
|
|
31788
31796
|
const GET_POSITION_PARTIALS_METHOD_NAME = "strategy.getPositionPartials";
|
|
31797
|
+
const GET_POSITION_ENTRY_OVERLAP_METHOD_NAME = "strategy.getPositionEntryOverlap";
|
|
31798
|
+
const GET_POSITION_PARTIAL_OVERLAP_METHOD_NAME = "strategy.getPositionPartialOverlap";
|
|
31789
31799
|
/**
|
|
31790
31800
|
* Cancels the scheduled signal without stopping the strategy.
|
|
31791
31801
|
*
|
|
@@ -32062,6 +32072,7 @@ async function commitTrailingStop(symbol, percentShift, currentPrice) {
|
|
|
32062
32072
|
percentShift,
|
|
32063
32073
|
currentPrice,
|
|
32064
32074
|
newStopLossPrice: slPercentShiftToPrice(percentShift, signal.priceStopLoss, effectivePriceOpen, signal.position),
|
|
32075
|
+
takeProfitPrice: signal.priceTakeProfit,
|
|
32065
32076
|
position: signal.position,
|
|
32066
32077
|
context: { exchangeName, frameName, strategyName },
|
|
32067
32078
|
backtest: isBacktest,
|
|
@@ -32141,6 +32152,7 @@ async function commitTrailingTake(symbol, percentShift, currentPrice) {
|
|
|
32141
32152
|
percentShift,
|
|
32142
32153
|
currentPrice,
|
|
32143
32154
|
newTakeProfitPrice: tpPercentShiftToPrice(percentShift, signal.priceTakeProfit, effectivePriceOpen, signal.position),
|
|
32155
|
+
takeProfitPrice: signal.priceTakeProfit,
|
|
32144
32156
|
position: signal.position,
|
|
32145
32157
|
context: { exchangeName, frameName, strategyName },
|
|
32146
32158
|
backtest: isBacktest,
|
|
@@ -32192,6 +32204,7 @@ async function commitTrailingStopCost(symbol, newStopLossPrice) {
|
|
|
32192
32204
|
currentPrice,
|
|
32193
32205
|
newStopLossPrice,
|
|
32194
32206
|
position: signal.position,
|
|
32207
|
+
takeProfitPrice: signal.priceTakeProfit,
|
|
32195
32208
|
context: { exchangeName, frameName, strategyName },
|
|
32196
32209
|
backtest: isBacktest,
|
|
32197
32210
|
});
|
|
@@ -32241,6 +32254,7 @@ async function commitTrailingTakeCost(symbol, newTakeProfitPrice) {
|
|
|
32241
32254
|
percentShift,
|
|
32242
32255
|
currentPrice,
|
|
32243
32256
|
newTakeProfitPrice,
|
|
32257
|
+
takeProfitPrice: signal.priceTakeProfit,
|
|
32244
32258
|
position: signal.position,
|
|
32245
32259
|
context: { exchangeName, frameName, strategyName },
|
|
32246
32260
|
backtest: isBacktest,
|
|
@@ -32567,6 +32581,31 @@ async function getBreakeven(symbol, currentPrice) {
|
|
|
32567
32581
|
const { exchangeName, frameName, strategyName } = bt.methodContextService.context;
|
|
32568
32582
|
return await bt.strategyCoreService.getBreakeven(isBacktest, symbol, currentPrice, { exchangeName, frameName, strategyName });
|
|
32569
32583
|
}
|
|
32584
|
+
/**
|
|
32585
|
+
* Returns the effective (DCA-weighted) entry price for the current pending signal.
|
|
32586
|
+
*
|
|
32587
|
+
* Uses cost-weighted harmonic mean: Σcost / Σ(cost/price).
|
|
32588
|
+
* When partial closes exist, the price is computed iteratively using
|
|
32589
|
+
* costBasisAtClose snapshots from each partial, then blended with any
|
|
32590
|
+
* DCA entries added after the last partial.
|
|
32591
|
+
* With no DCA entries, equals the original priceOpen.
|
|
32592
|
+
*
|
|
32593
|
+
* Returns null if no pending signal exists.
|
|
32594
|
+
*
|
|
32595
|
+
* Automatically detects backtest/live mode from execution context.
|
|
32596
|
+
*
|
|
32597
|
+
* @param symbol - Trading pair symbol
|
|
32598
|
+
* @returns Promise resolving to effective entry price or null
|
|
32599
|
+
*
|
|
32600
|
+
* @example
|
|
32601
|
+
* ```typescript
|
|
32602
|
+
* import { getPositionAveragePrice } from "backtest-kit";
|
|
32603
|
+
*
|
|
32604
|
+
* const avgPrice = await getPositionAveragePrice("BTCUSDT");
|
|
32605
|
+
* // No DCA: avgPrice === priceOpen
|
|
32606
|
+
* // After DCA at lower price: avgPrice < priceOpen
|
|
32607
|
+
* ```
|
|
32608
|
+
*/
|
|
32570
32609
|
async function getPositionAveragePrice(symbol) {
|
|
32571
32610
|
bt.loggerService.info(GET_POSITION_AVERAGE_PRICE_METHOD_NAME, {
|
|
32572
32611
|
symbol,
|
|
@@ -32581,6 +32620,28 @@ async function getPositionAveragePrice(symbol) {
|
|
|
32581
32620
|
const { exchangeName, frameName, strategyName } = bt.methodContextService.context;
|
|
32582
32621
|
return await bt.strategyCoreService.getPositionAveragePrice(isBacktest, symbol, { exchangeName, frameName, strategyName });
|
|
32583
32622
|
}
|
|
32623
|
+
/**
|
|
32624
|
+
* Returns the number of DCA entries made for the current pending signal.
|
|
32625
|
+
*
|
|
32626
|
+
* 1 = original entry only (no DCA).
|
|
32627
|
+
* Increases by 1 with each successful commitAverageBuy().
|
|
32628
|
+
*
|
|
32629
|
+
* Returns null if no pending signal exists.
|
|
32630
|
+
*
|
|
32631
|
+
* Automatically detects backtest/live mode from execution context.
|
|
32632
|
+
*
|
|
32633
|
+
* @param symbol - Trading pair symbol
|
|
32634
|
+
* @returns Promise resolving to entry count or null
|
|
32635
|
+
*
|
|
32636
|
+
* @example
|
|
32637
|
+
* ```typescript
|
|
32638
|
+
* import { getPositionInvestedCount } from "backtest-kit";
|
|
32639
|
+
*
|
|
32640
|
+
* const count = await getPositionInvestedCount("BTCUSDT");
|
|
32641
|
+
* // No DCA: count === 1
|
|
32642
|
+
* // After one DCA: count === 2
|
|
32643
|
+
* ```
|
|
32644
|
+
*/
|
|
32584
32645
|
async function getPositionInvestedCount(symbol) {
|
|
32585
32646
|
bt.loggerService.info(GET_POSITION_INVESTED_COUNT_METHOD_NAME, {
|
|
32586
32647
|
symbol,
|
|
@@ -32595,6 +32656,28 @@ async function getPositionInvestedCount(symbol) {
|
|
|
32595
32656
|
const { exchangeName, frameName, strategyName } = bt.methodContextService.context;
|
|
32596
32657
|
return await bt.strategyCoreService.getPositionInvestedCount(isBacktest, symbol, { exchangeName, frameName, strategyName });
|
|
32597
32658
|
}
|
|
32659
|
+
/**
|
|
32660
|
+
* Returns the total invested cost basis in dollars for the current pending signal.
|
|
32661
|
+
*
|
|
32662
|
+
* Equal to the sum of all _entry costs (Σ entry.cost).
|
|
32663
|
+
* Each entry cost is set at the time of commitAverageBuy (defaults to CC_POSITION_ENTRY_COST).
|
|
32664
|
+
*
|
|
32665
|
+
* Returns null if no pending signal exists.
|
|
32666
|
+
*
|
|
32667
|
+
* Automatically detects backtest/live mode from execution context.
|
|
32668
|
+
*
|
|
32669
|
+
* @param symbol - Trading pair symbol
|
|
32670
|
+
* @returns Promise resolving to total invested cost in dollars or null
|
|
32671
|
+
*
|
|
32672
|
+
* @example
|
|
32673
|
+
* ```typescript
|
|
32674
|
+
* import { getPositionInvestedCost } from "backtest-kit";
|
|
32675
|
+
*
|
|
32676
|
+
* const cost = await getPositionInvestedCost("BTCUSDT");
|
|
32677
|
+
* // No DCA, default cost: cost === 100
|
|
32678
|
+
* // After one DCA with default cost: cost === 200
|
|
32679
|
+
* ```
|
|
32680
|
+
*/
|
|
32598
32681
|
async function getPositionInvestedCost(symbol) {
|
|
32599
32682
|
bt.loggerService.info(GET_POSITION_INVESTED_COST_METHOD_NAME, {
|
|
32600
32683
|
symbol,
|
|
@@ -32609,6 +32692,29 @@ async function getPositionInvestedCost(symbol) {
|
|
|
32609
32692
|
const { exchangeName, frameName, strategyName } = bt.methodContextService.context;
|
|
32610
32693
|
return await bt.strategyCoreService.getPositionInvestedCost(isBacktest, symbol, { exchangeName, frameName, strategyName });
|
|
32611
32694
|
}
|
|
32695
|
+
/**
|
|
32696
|
+
* Returns the unrealized PNL percentage for the current pending signal at current market price.
|
|
32697
|
+
*
|
|
32698
|
+
* Accounts for partial closes, DCA entries, slippage and fees
|
|
32699
|
+
* (delegates to toProfitLossDto).
|
|
32700
|
+
*
|
|
32701
|
+
* Returns null if no pending signal exists.
|
|
32702
|
+
*
|
|
32703
|
+
* Automatically detects backtest/live mode from execution context.
|
|
32704
|
+
* Automatically fetches current price via getAveragePrice.
|
|
32705
|
+
*
|
|
32706
|
+
* @param symbol - Trading pair symbol
|
|
32707
|
+
* @returns Promise resolving to PNL percentage or null
|
|
32708
|
+
*
|
|
32709
|
+
* @example
|
|
32710
|
+
* ```typescript
|
|
32711
|
+
* import { getPositionPnlPercent } from "backtest-kit";
|
|
32712
|
+
*
|
|
32713
|
+
* const pnlPct = await getPositionPnlPercent("BTCUSDT");
|
|
32714
|
+
* // LONG at 100, current=105: pnlPct ≈ 5
|
|
32715
|
+
* // LONG at 100, current=95: pnlPct ≈ -5
|
|
32716
|
+
* ```
|
|
32717
|
+
*/
|
|
32612
32718
|
async function getPositionPnlPercent(symbol) {
|
|
32613
32719
|
bt.loggerService.info(GET_POSITION_PNL_PERCENT_METHOD_NAME, { symbol });
|
|
32614
32720
|
if (!ExecutionContextService.hasContext()) {
|
|
@@ -32758,6 +32864,29 @@ async function commitPartialLossCost(symbol, dollarAmount) {
|
|
|
32758
32864
|
});
|
|
32759
32865
|
return await bt.strategyCoreService.partialLoss(isBacktest, symbol, percentToClose, currentPrice, { exchangeName, frameName, strategyName });
|
|
32760
32866
|
}
|
|
32867
|
+
/**
|
|
32868
|
+
* Returns the unrealized PNL in dollars for the current pending signal at current market price.
|
|
32869
|
+
*
|
|
32870
|
+
* Calculated as: pnlPercentage / 100 × totalInvestedCost.
|
|
32871
|
+
* Accounts for partial closes, DCA entries, slippage and fees.
|
|
32872
|
+
*
|
|
32873
|
+
* Returns null if no pending signal exists.
|
|
32874
|
+
*
|
|
32875
|
+
* Automatically detects backtest/live mode from execution context.
|
|
32876
|
+
* Automatically fetches current price via getAveragePrice.
|
|
32877
|
+
*
|
|
32878
|
+
* @param symbol - Trading pair symbol
|
|
32879
|
+
* @returns Promise resolving to PNL in dollars or null
|
|
32880
|
+
*
|
|
32881
|
+
* @example
|
|
32882
|
+
* ```typescript
|
|
32883
|
+
* import { getPositionPnlCost } from "backtest-kit";
|
|
32884
|
+
*
|
|
32885
|
+
* const pnlCost = await getPositionPnlCost("BTCUSDT");
|
|
32886
|
+
* // LONG at 100, invested $100, current=105: pnlCost ≈ 5
|
|
32887
|
+
* // LONG at 100, invested $200 (DCA), current=95: pnlCost ≈ -10
|
|
32888
|
+
* ```
|
|
32889
|
+
*/
|
|
32761
32890
|
async function getPositionPnlCost(symbol) {
|
|
32762
32891
|
bt.loggerService.info(GET_POSITION_PNL_COST_METHOD_NAME, { symbol });
|
|
32763
32892
|
if (!ExecutionContextService.hasContext()) {
|
|
@@ -32844,6 +32973,104 @@ async function getPositionPartials(symbol) {
|
|
|
32844
32973
|
const { exchangeName, frameName, strategyName } = bt.methodContextService.context;
|
|
32845
32974
|
return await bt.strategyCoreService.getPositionPartials(isBacktest, symbol, { exchangeName, frameName, strategyName });
|
|
32846
32975
|
}
|
|
32976
|
+
/**
|
|
32977
|
+
* Checks whether the current price falls within the tolerance zone of any existing DCA entry level.
|
|
32978
|
+
* Use this to prevent duplicate DCA entries at the same price area.
|
|
32979
|
+
*
|
|
32980
|
+
* Returns true if currentPrice is within [level - lowerStep, level + upperStep] for any level,
|
|
32981
|
+
* where step = level * percent / 100.
|
|
32982
|
+
* Returns false if no pending signal exists.
|
|
32983
|
+
*
|
|
32984
|
+
* @param symbol - Trading pair symbol
|
|
32985
|
+
* @param currentPrice - Price to check against existing DCA levels
|
|
32986
|
+
* @param ladder - Tolerance zone config; percentages in 0–100 format (default: 1.5% up and down)
|
|
32987
|
+
* @returns Promise<boolean> - true if price overlaps an existing entry level (DCA not recommended)
|
|
32988
|
+
*
|
|
32989
|
+
* @example
|
|
32990
|
+
* ```typescript
|
|
32991
|
+
* import { getPositionEntryOverlap } from "backtest-kit";
|
|
32992
|
+
*
|
|
32993
|
+
* // LONG with levels [43000, 42000], check if 42100 is too close to 42000
|
|
32994
|
+
* const overlap = await getPositionEntryOverlap("BTCUSDT", 42100, { upperPercent: 5, lowerPercent: 5 });
|
|
32995
|
+
* // overlap = true (42100 is within 5% of 42000 = [39900, 44100])
|
|
32996
|
+
* if (!overlap) {
|
|
32997
|
+
* await commitAverageBuy("BTCUSDT");
|
|
32998
|
+
* }
|
|
32999
|
+
* ```
|
|
33000
|
+
*/
|
|
33001
|
+
async function getPositionEntryOverlap(symbol, currentPrice, ladder = POSITION_OVERLAP_LADDER_DEFAULT) {
|
|
33002
|
+
bt.loggerService.info(GET_POSITION_ENTRY_OVERLAP_METHOD_NAME, {
|
|
33003
|
+
symbol,
|
|
33004
|
+
currentPrice,
|
|
33005
|
+
ladder,
|
|
33006
|
+
});
|
|
33007
|
+
if (!ExecutionContextService.hasContext()) {
|
|
33008
|
+
throw new Error("getPositionEntryOverlap requires an execution context");
|
|
33009
|
+
}
|
|
33010
|
+
if (!MethodContextService.hasContext()) {
|
|
33011
|
+
throw new Error("getPositionEntryOverlap requires a method context");
|
|
33012
|
+
}
|
|
33013
|
+
const { backtest: isBacktest } = bt.executionContextService.context;
|
|
33014
|
+
const { exchangeName, frameName, strategyName } = bt.methodContextService.context;
|
|
33015
|
+
const levels = await bt.strategyCoreService.getPositionLevels(isBacktest, symbol, { exchangeName, frameName, strategyName });
|
|
33016
|
+
if (!levels) {
|
|
33017
|
+
return false;
|
|
33018
|
+
}
|
|
33019
|
+
return levels.some((level) => {
|
|
33020
|
+
const upperStep = (level * ladder.upperPercent) / 100;
|
|
33021
|
+
const lowerStep = (level * ladder.lowerPercent) / 100;
|
|
33022
|
+
return currentPrice >= level - lowerStep && currentPrice <= level + upperStep;
|
|
33023
|
+
});
|
|
33024
|
+
}
|
|
33025
|
+
/**
|
|
33026
|
+
* Checks whether the current price falls within the tolerance zone of any existing partial close price.
|
|
33027
|
+
* Use this to prevent duplicate partial closes at the same price area.
|
|
33028
|
+
*
|
|
33029
|
+
* Returns true if currentPrice is within [partial.currentPrice - lowerStep, partial.currentPrice + upperStep]
|
|
33030
|
+
* for any partial, where step = partial.currentPrice * percent / 100.
|
|
33031
|
+
* Returns false if no pending signal exists or no partials have been executed yet.
|
|
33032
|
+
*
|
|
33033
|
+
* @param symbol - Trading pair symbol
|
|
33034
|
+
* @param currentPrice - Price to check against existing partial close prices
|
|
33035
|
+
* @param ladder - Tolerance zone config; percentages in 0–100 format (default: 1.5% up and down)
|
|
33036
|
+
* @returns Promise<boolean> - true if price overlaps an existing partial price (partial not recommended)
|
|
33037
|
+
*
|
|
33038
|
+
* @example
|
|
33039
|
+
* ```typescript
|
|
33040
|
+
* import { getPositionPartialOverlap } from "backtest-kit";
|
|
33041
|
+
*
|
|
33042
|
+
* // Partials at [45000], check if 45100 is too close
|
|
33043
|
+
* const overlap = await getPositionPartialOverlap("BTCUSDT", 45100, { upperPercent: 1.5, lowerPercent: 1.5 });
|
|
33044
|
+
* // overlap = true (45100 is within 1.5% of 45000)
|
|
33045
|
+
* if (!overlap) {
|
|
33046
|
+
* await commitPartialProfit("BTCUSDT", 50);
|
|
33047
|
+
* }
|
|
33048
|
+
* ```
|
|
33049
|
+
*/
|
|
33050
|
+
async function getPositionPartialOverlap(symbol, currentPrice, ladder = POSITION_OVERLAP_LADDER_DEFAULT) {
|
|
33051
|
+
bt.loggerService.info(GET_POSITION_PARTIAL_OVERLAP_METHOD_NAME, {
|
|
33052
|
+
symbol,
|
|
33053
|
+
currentPrice,
|
|
33054
|
+
ladder,
|
|
33055
|
+
});
|
|
33056
|
+
if (!ExecutionContextService.hasContext()) {
|
|
33057
|
+
throw new Error("getPositionPartialOverlap requires an execution context");
|
|
33058
|
+
}
|
|
33059
|
+
if (!MethodContextService.hasContext()) {
|
|
33060
|
+
throw new Error("getPositionPartialOverlap requires a method context");
|
|
33061
|
+
}
|
|
33062
|
+
const { backtest: isBacktest } = bt.executionContextService.context;
|
|
33063
|
+
const { exchangeName, frameName, strategyName } = bt.methodContextService.context;
|
|
33064
|
+
const partials = await bt.strategyCoreService.getPositionPartials(isBacktest, symbol, { exchangeName, frameName, strategyName });
|
|
33065
|
+
if (!partials) {
|
|
33066
|
+
return false;
|
|
33067
|
+
}
|
|
33068
|
+
return partials.some((partial) => {
|
|
33069
|
+
const upperStep = (partial.currentPrice * ladder.upperPercent) / 100;
|
|
33070
|
+
const lowerStep = (partial.currentPrice * ladder.lowerPercent) / 100;
|
|
33071
|
+
return currentPrice >= partial.currentPrice - lowerStep && currentPrice <= partial.currentPrice + upperStep;
|
|
33072
|
+
});
|
|
33073
|
+
}
|
|
32847
33074
|
|
|
32848
33075
|
const STOP_STRATEGY_METHOD_NAME = "control.stopStrategy";
|
|
32849
33076
|
/**
|
|
@@ -34070,6 +34297,8 @@ const BACKTEST_METHOD_NAME_GET_POSITION_PNL_COST = "BacktestUtils.getPositionPnl
|
|
|
34070
34297
|
const BACKTEST_METHOD_NAME_GET_POSITION_LEVELS = "BacktestUtils.getPositionLevels";
|
|
34071
34298
|
const BACKTEST_METHOD_NAME_GET_POSITION_PARTIALS = "BacktestUtils.getPositionPartials";
|
|
34072
34299
|
const BACKTEST_METHOD_NAME_GET_POSITION_ENTRIES = "BacktestUtils.getPositionEntries";
|
|
34300
|
+
const BACKTEST_METHOD_NAME_GET_POSITION_ENTRY_OVERLAP = "BacktestUtils.getPositionEntryOverlap";
|
|
34301
|
+
const BACKTEST_METHOD_NAME_GET_POSITION_PARTIAL_OVERLAP = "BacktestUtils.getPositionPartialOverlap";
|
|
34073
34302
|
const BACKTEST_METHOD_NAME_BREAKEVEN = "Backtest.commitBreakeven";
|
|
34074
34303
|
const BACKTEST_METHOD_NAME_CANCEL_SCHEDULED = "Backtest.commitCancelScheduled";
|
|
34075
34304
|
const BACKTEST_METHOD_NAME_CLOSE_PENDING = "Backtest.commitClosePending";
|
|
@@ -34860,6 +35089,90 @@ class BacktestUtils {
|
|
|
34860
35089
|
}
|
|
34861
35090
|
return await bt.strategyCoreService.getPositionEntries(true, symbol, context);
|
|
34862
35091
|
};
|
|
35092
|
+
/**
|
|
35093
|
+
* Checks whether the current price falls within the tolerance zone of any existing DCA entry level.
|
|
35094
|
+
* Use this to prevent duplicate DCA entries at the same price area.
|
|
35095
|
+
*
|
|
35096
|
+
* Returns true if currentPrice is within [level - lowerStep, level + upperStep] for any level,
|
|
35097
|
+
* where step = level * percent / 100.
|
|
35098
|
+
* Returns false if no pending signal exists.
|
|
35099
|
+
*
|
|
35100
|
+
* @param symbol - Trading pair symbol
|
|
35101
|
+
* @param currentPrice - Price to check against existing DCA levels
|
|
35102
|
+
* @param context - Execution context with strategyName, exchangeName, and frameName
|
|
35103
|
+
* @param ladder - Tolerance zone config; percentages in 0–100 format (default: 1.5% up and down)
|
|
35104
|
+
* @returns true if price overlaps an existing entry level (DCA not recommended)
|
|
35105
|
+
*/
|
|
35106
|
+
this.getPositionEntryOverlap = async (symbol, currentPrice, context, ladder = POSITION_OVERLAP_LADDER_DEFAULT) => {
|
|
35107
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_GET_POSITION_ENTRY_OVERLAP, {
|
|
35108
|
+
symbol,
|
|
35109
|
+
currentPrice,
|
|
35110
|
+
context,
|
|
35111
|
+
ladder,
|
|
35112
|
+
});
|
|
35113
|
+
bt.strategyValidationService.validate(context.strategyName, BACKTEST_METHOD_NAME_GET_POSITION_ENTRY_OVERLAP);
|
|
35114
|
+
bt.exchangeValidationService.validate(context.exchangeName, BACKTEST_METHOD_NAME_GET_POSITION_ENTRY_OVERLAP);
|
|
35115
|
+
{
|
|
35116
|
+
const { riskName, riskList, actions } = bt.strategySchemaService.get(context.strategyName);
|
|
35117
|
+
riskName &&
|
|
35118
|
+
bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_GET_POSITION_ENTRY_OVERLAP);
|
|
35119
|
+
riskList &&
|
|
35120
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_GET_POSITION_ENTRY_OVERLAP));
|
|
35121
|
+
actions &&
|
|
35122
|
+
actions.forEach((actionName) => bt.actionValidationService.validate(actionName, BACKTEST_METHOD_NAME_GET_POSITION_ENTRY_OVERLAP));
|
|
35123
|
+
}
|
|
35124
|
+
const levels = await bt.strategyCoreService.getPositionLevels(true, symbol, context);
|
|
35125
|
+
if (!levels) {
|
|
35126
|
+
return false;
|
|
35127
|
+
}
|
|
35128
|
+
return levels.some((level) => {
|
|
35129
|
+
const upperStep = (level * ladder.upperPercent) / 100;
|
|
35130
|
+
const lowerStep = (level * ladder.lowerPercent) / 100;
|
|
35131
|
+
return currentPrice >= level - lowerStep && currentPrice <= level + upperStep;
|
|
35132
|
+
});
|
|
35133
|
+
};
|
|
35134
|
+
/**
|
|
35135
|
+
* Checks whether the current price falls within the tolerance zone of any existing partial close price.
|
|
35136
|
+
* Use this to prevent duplicate partial closes at the same price area.
|
|
35137
|
+
*
|
|
35138
|
+
* Returns true if currentPrice is within [partial.currentPrice - lowerStep, partial.currentPrice + upperStep]
|
|
35139
|
+
* for any partial, where step = partial.currentPrice * percent / 100.
|
|
35140
|
+
* Returns false if no pending signal exists or no partials have been executed yet.
|
|
35141
|
+
*
|
|
35142
|
+
* @param symbol - Trading pair symbol
|
|
35143
|
+
* @param currentPrice - Price to check against existing partial close prices
|
|
35144
|
+
* @param context - Execution context with strategyName, exchangeName, and frameName
|
|
35145
|
+
* @param ladder - Tolerance zone config; percentages in 0–100 format (default: 1.5% up and down)
|
|
35146
|
+
* @returns true if price overlaps an existing partial price (partial not recommended)
|
|
35147
|
+
*/
|
|
35148
|
+
this.getPositionPartialOverlap = async (symbol, currentPrice, context, ladder = POSITION_OVERLAP_LADDER_DEFAULT) => {
|
|
35149
|
+
bt.loggerService.info(BACKTEST_METHOD_NAME_GET_POSITION_PARTIAL_OVERLAP, {
|
|
35150
|
+
symbol,
|
|
35151
|
+
currentPrice,
|
|
35152
|
+
context,
|
|
35153
|
+
ladder,
|
|
35154
|
+
});
|
|
35155
|
+
bt.strategyValidationService.validate(context.strategyName, BACKTEST_METHOD_NAME_GET_POSITION_PARTIAL_OVERLAP);
|
|
35156
|
+
bt.exchangeValidationService.validate(context.exchangeName, BACKTEST_METHOD_NAME_GET_POSITION_PARTIAL_OVERLAP);
|
|
35157
|
+
{
|
|
35158
|
+
const { riskName, riskList, actions } = bt.strategySchemaService.get(context.strategyName);
|
|
35159
|
+
riskName &&
|
|
35160
|
+
bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_GET_POSITION_PARTIAL_OVERLAP);
|
|
35161
|
+
riskList &&
|
|
35162
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_GET_POSITION_PARTIAL_OVERLAP));
|
|
35163
|
+
actions &&
|
|
35164
|
+
actions.forEach((actionName) => bt.actionValidationService.validate(actionName, BACKTEST_METHOD_NAME_GET_POSITION_PARTIAL_OVERLAP));
|
|
35165
|
+
}
|
|
35166
|
+
const partials = await bt.strategyCoreService.getPositionPartials(true, symbol, context);
|
|
35167
|
+
if (!partials) {
|
|
35168
|
+
return false;
|
|
35169
|
+
}
|
|
35170
|
+
return partials.some((partial) => {
|
|
35171
|
+
const upperStep = (partial.currentPrice * ladder.upperPercent) / 100;
|
|
35172
|
+
const lowerStep = (partial.currentPrice * ladder.lowerPercent) / 100;
|
|
35173
|
+
return currentPrice >= partial.currentPrice - lowerStep && currentPrice <= partial.currentPrice + upperStep;
|
|
35174
|
+
});
|
|
35175
|
+
};
|
|
34863
35176
|
/**
|
|
34864
35177
|
* Stops the strategy from generating new signals.
|
|
34865
35178
|
*
|
|
@@ -35349,6 +35662,7 @@ class BacktestUtils {
|
|
|
35349
35662
|
percentShift,
|
|
35350
35663
|
currentPrice,
|
|
35351
35664
|
newStopLossPrice: slPercentShiftToPrice(percentShift, signal.priceStopLoss, effectivePriceOpen, signal.position),
|
|
35665
|
+
takeProfitPrice: signal.priceTakeProfit,
|
|
35352
35666
|
position: signal.position,
|
|
35353
35667
|
context,
|
|
35354
35668
|
backtest: true,
|
|
@@ -35433,6 +35747,7 @@ class BacktestUtils {
|
|
|
35433
35747
|
percentShift,
|
|
35434
35748
|
currentPrice,
|
|
35435
35749
|
newTakeProfitPrice: tpPercentShiftToPrice(percentShift, signal.priceTakeProfit, effectivePriceOpen, signal.position),
|
|
35750
|
+
takeProfitPrice: signal.priceTakeProfit,
|
|
35436
35751
|
position: signal.position,
|
|
35437
35752
|
context,
|
|
35438
35753
|
backtest: true,
|
|
@@ -35487,6 +35802,7 @@ class BacktestUtils {
|
|
|
35487
35802
|
currentPrice,
|
|
35488
35803
|
newStopLossPrice,
|
|
35489
35804
|
position: signal.position,
|
|
35805
|
+
takeProfitPrice: signal.priceTakeProfit,
|
|
35490
35806
|
context,
|
|
35491
35807
|
backtest: true,
|
|
35492
35808
|
});
|
|
@@ -35540,6 +35856,7 @@ class BacktestUtils {
|
|
|
35540
35856
|
currentPrice,
|
|
35541
35857
|
newTakeProfitPrice,
|
|
35542
35858
|
position: signal.position,
|
|
35859
|
+
takeProfitPrice: signal.priceTakeProfit,
|
|
35543
35860
|
context,
|
|
35544
35861
|
backtest: true,
|
|
35545
35862
|
});
|
|
@@ -35883,6 +36200,8 @@ const LIVE_METHOD_NAME_GET_POSITION_PNL_COST = "LiveUtils.getPositionPnlCost";
|
|
|
35883
36200
|
const LIVE_METHOD_NAME_GET_POSITION_LEVELS = "LiveUtils.getPositionLevels";
|
|
35884
36201
|
const LIVE_METHOD_NAME_GET_POSITION_PARTIALS = "LiveUtils.getPositionPartials";
|
|
35885
36202
|
const LIVE_METHOD_NAME_GET_POSITION_ENTRIES = "LiveUtils.getPositionEntries";
|
|
36203
|
+
const LIVE_METHOD_NAME_GET_POSITION_ENTRY_OVERLAP = "LiveUtils.getPositionEntryOverlap";
|
|
36204
|
+
const LIVE_METHOD_NAME_GET_POSITION_PARTIAL_OVERLAP = "LiveUtils.getPositionPartialOverlap";
|
|
35886
36205
|
const LIVE_METHOD_NAME_BREAKEVEN = "Live.commitBreakeven";
|
|
35887
36206
|
const LIVE_METHOD_NAME_CANCEL_SCHEDULED = "Live.cancelScheduled";
|
|
35888
36207
|
const LIVE_METHOD_NAME_CLOSE_PENDING = "Live.closePending";
|
|
@@ -36736,6 +37055,98 @@ class LiveUtils {
|
|
|
36736
37055
|
frameName: "",
|
|
36737
37056
|
});
|
|
36738
37057
|
};
|
|
37058
|
+
/**
|
|
37059
|
+
* Checks whether the current price falls within the tolerance zone of any existing DCA entry level.
|
|
37060
|
+
* Use this to prevent duplicate DCA entries at the same price area.
|
|
37061
|
+
*
|
|
37062
|
+
* Returns true if currentPrice is within [level - lowerStep, level + upperStep] for any level,
|
|
37063
|
+
* where step = level * percent / 100.
|
|
37064
|
+
* Returns false if no pending signal exists.
|
|
37065
|
+
*
|
|
37066
|
+
* @param symbol - Trading pair symbol
|
|
37067
|
+
* @param currentPrice - Price to check against existing DCA levels
|
|
37068
|
+
* @param context - Execution context with strategyName and exchangeName
|
|
37069
|
+
* @param ladder - Tolerance zone config; percentages in 0–100 format (default: 1.5% up and down)
|
|
37070
|
+
* @returns true if price overlaps an existing entry level (DCA not recommended)
|
|
37071
|
+
*/
|
|
37072
|
+
this.getPositionEntryOverlap = async (symbol, currentPrice, context, ladder = POSITION_OVERLAP_LADDER_DEFAULT) => {
|
|
37073
|
+
bt.loggerService.info(LIVE_METHOD_NAME_GET_POSITION_ENTRY_OVERLAP, {
|
|
37074
|
+
symbol,
|
|
37075
|
+
currentPrice,
|
|
37076
|
+
context,
|
|
37077
|
+
ladder,
|
|
37078
|
+
});
|
|
37079
|
+
bt.strategyValidationService.validate(context.strategyName, LIVE_METHOD_NAME_GET_POSITION_ENTRY_OVERLAP);
|
|
37080
|
+
bt.exchangeValidationService.validate(context.exchangeName, LIVE_METHOD_NAME_GET_POSITION_ENTRY_OVERLAP);
|
|
37081
|
+
{
|
|
37082
|
+
const { riskName, riskList, actions } = bt.strategySchemaService.get(context.strategyName);
|
|
37083
|
+
riskName &&
|
|
37084
|
+
bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_GET_POSITION_ENTRY_OVERLAP);
|
|
37085
|
+
riskList &&
|
|
37086
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_GET_POSITION_ENTRY_OVERLAP));
|
|
37087
|
+
actions &&
|
|
37088
|
+
actions.forEach((actionName) => bt.actionValidationService.validate(actionName, LIVE_METHOD_NAME_GET_POSITION_ENTRY_OVERLAP));
|
|
37089
|
+
}
|
|
37090
|
+
const levels = await bt.strategyCoreService.getPositionLevels(false, symbol, {
|
|
37091
|
+
strategyName: context.strategyName,
|
|
37092
|
+
exchangeName: context.exchangeName,
|
|
37093
|
+
frameName: "",
|
|
37094
|
+
});
|
|
37095
|
+
if (!levels) {
|
|
37096
|
+
return false;
|
|
37097
|
+
}
|
|
37098
|
+
return levels.some((level) => {
|
|
37099
|
+
const upperStep = (level * ladder.upperPercent) / 100;
|
|
37100
|
+
const lowerStep = (level * ladder.lowerPercent) / 100;
|
|
37101
|
+
return currentPrice >= level - lowerStep && currentPrice <= level + upperStep;
|
|
37102
|
+
});
|
|
37103
|
+
};
|
|
37104
|
+
/**
|
|
37105
|
+
* Checks whether the current price falls within the tolerance zone of any existing partial close price.
|
|
37106
|
+
* Use this to prevent duplicate partial closes at the same price area.
|
|
37107
|
+
*
|
|
37108
|
+
* Returns true if currentPrice is within [partial.currentPrice - lowerStep, partial.currentPrice + upperStep]
|
|
37109
|
+
* for any partial, where step = partial.currentPrice * percent / 100.
|
|
37110
|
+
* Returns false if no pending signal exists or no partials have been executed yet.
|
|
37111
|
+
*
|
|
37112
|
+
* @param symbol - Trading pair symbol
|
|
37113
|
+
* @param currentPrice - Price to check against existing partial close prices
|
|
37114
|
+
* @param context - Execution context with strategyName and exchangeName
|
|
37115
|
+
* @param ladder - Tolerance zone config; percentages in 0–100 format (default: 1.5% up and down)
|
|
37116
|
+
* @returns true if price overlaps an existing partial price (partial not recommended)
|
|
37117
|
+
*/
|
|
37118
|
+
this.getPositionPartialOverlap = async (symbol, currentPrice, context, ladder = POSITION_OVERLAP_LADDER_DEFAULT) => {
|
|
37119
|
+
bt.loggerService.info(LIVE_METHOD_NAME_GET_POSITION_PARTIAL_OVERLAP, {
|
|
37120
|
+
symbol,
|
|
37121
|
+
currentPrice,
|
|
37122
|
+
context,
|
|
37123
|
+
ladder,
|
|
37124
|
+
});
|
|
37125
|
+
bt.strategyValidationService.validate(context.strategyName, LIVE_METHOD_NAME_GET_POSITION_PARTIAL_OVERLAP);
|
|
37126
|
+
bt.exchangeValidationService.validate(context.exchangeName, LIVE_METHOD_NAME_GET_POSITION_PARTIAL_OVERLAP);
|
|
37127
|
+
{
|
|
37128
|
+
const { riskName, riskList, actions } = bt.strategySchemaService.get(context.strategyName);
|
|
37129
|
+
riskName &&
|
|
37130
|
+
bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_GET_POSITION_PARTIAL_OVERLAP);
|
|
37131
|
+
riskList &&
|
|
37132
|
+
riskList.forEach((riskName) => bt.riskValidationService.validate(riskName, LIVE_METHOD_NAME_GET_POSITION_PARTIAL_OVERLAP));
|
|
37133
|
+
actions &&
|
|
37134
|
+
actions.forEach((actionName) => bt.actionValidationService.validate(actionName, LIVE_METHOD_NAME_GET_POSITION_PARTIAL_OVERLAP));
|
|
37135
|
+
}
|
|
37136
|
+
const partials = await bt.strategyCoreService.getPositionPartials(false, symbol, {
|
|
37137
|
+
strategyName: context.strategyName,
|
|
37138
|
+
exchangeName: context.exchangeName,
|
|
37139
|
+
frameName: "",
|
|
37140
|
+
});
|
|
37141
|
+
if (!partials) {
|
|
37142
|
+
return false;
|
|
37143
|
+
}
|
|
37144
|
+
return partials.some((partial) => {
|
|
37145
|
+
const upperStep = (partial.currentPrice * ladder.upperPercent) / 100;
|
|
37146
|
+
const lowerStep = (partial.currentPrice * ladder.lowerPercent) / 100;
|
|
37147
|
+
return currentPrice >= partial.currentPrice - lowerStep && currentPrice <= partial.currentPrice + upperStep;
|
|
37148
|
+
});
|
|
37149
|
+
};
|
|
36739
37150
|
/**
|
|
36740
37151
|
* Stops the strategy from generating new signals.
|
|
36741
37152
|
*
|
|
@@ -37318,6 +37729,7 @@ class LiveUtils {
|
|
|
37318
37729
|
percentShift,
|
|
37319
37730
|
currentPrice,
|
|
37320
37731
|
newStopLossPrice: slPercentShiftToPrice(percentShift, signal.priceStopLoss, effectivePriceOpen, signal.position),
|
|
37732
|
+
takeProfitPrice: signal.priceTakeProfit,
|
|
37321
37733
|
position: signal.position,
|
|
37322
37734
|
context,
|
|
37323
37735
|
backtest: false,
|
|
@@ -37417,6 +37829,7 @@ class LiveUtils {
|
|
|
37417
37829
|
percentShift,
|
|
37418
37830
|
currentPrice,
|
|
37419
37831
|
newTakeProfitPrice: tpPercentShiftToPrice(percentShift, signal.priceTakeProfit, effectivePriceOpen, signal.position),
|
|
37832
|
+
takeProfitPrice: signal.priceTakeProfit,
|
|
37420
37833
|
position: signal.position,
|
|
37421
37834
|
context,
|
|
37422
37835
|
backtest: false,
|
|
@@ -37486,6 +37899,7 @@ class LiveUtils {
|
|
|
37486
37899
|
percentShift,
|
|
37487
37900
|
currentPrice,
|
|
37488
37901
|
newStopLossPrice,
|
|
37902
|
+
takeProfitPrice: signal.priceTakeProfit,
|
|
37489
37903
|
position: signal.position,
|
|
37490
37904
|
context,
|
|
37491
37905
|
backtest: false,
|
|
@@ -37555,6 +37969,7 @@ class LiveUtils {
|
|
|
37555
37969
|
percentShift,
|
|
37556
37970
|
currentPrice,
|
|
37557
37971
|
newTakeProfitPrice,
|
|
37972
|
+
takeProfitPrice: signal.priceTakeProfit,
|
|
37558
37973
|
position: signal.position,
|
|
37559
37974
|
context,
|
|
37560
37975
|
backtest: false,
|
|
@@ -45465,4 +45880,4 @@ const percentValue = (yesterdayValue, todayValue) => {
|
|
|
45465
45880
|
return yesterdayValue / todayValue - 1;
|
|
45466
45881
|
};
|
|
45467
45882
|
|
|
45468
|
-
export { ActionBase, Backtest, Breakeven, Broker, BrokerBase, Cache, Constant, Exchange, ExecutionContextService, Heat, Live, Log, Markdown, MarkdownFileBase, MarkdownFolderBase, MethodContextService, Notification, NotificationBacktest, NotificationLive, Partial, Performance, PersistBase, PersistBreakevenAdapter, PersistCandleAdapter, PersistLogAdapter, PersistMeasureAdapter, PersistNotificationAdapter, PersistPartialAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistSignalAdapter, PersistStorageAdapter, PositionSize, Report, ReportBase, Risk, Schedule, Storage, StorageBacktest, StorageLive, Strategy, Sync, Walker, addActionSchema, addExchangeSchema, addFrameSchema, addRiskSchema, addSizingSchema, addStrategySchema, addWalkerSchema, alignToInterval, checkCandles, commitActivateScheduled, commitAverageBuy, commitBreakeven, commitCancelScheduled, commitClosePending, commitPartialLoss, commitPartialLossCost, commitPartialProfit, commitPartialProfitCost, commitTrailingStop, commitTrailingStopCost, commitTrailingTake, commitTrailingTakeCost, dumpMessages, emitters, formatPrice, formatQuantity, get, getActionSchema, getAggregatedTrades, getAveragePrice, getBacktestTimeframe, getBreakeven, getCandles, getColumns, getConfig, getContext, getDate, getDefaultColumns, getDefaultConfig, getEffectivePriceOpen, getExchangeSchema, getFrameSchema, getMode, getNextCandles, getOrderBook, getPendingSignal, getPositionAveragePrice, getPositionInvestedCost, getPositionInvestedCount, getPositionLevels, getPositionPartials, getPositionPnlCost, getPositionPnlPercent, getRawCandles, getRiskSchema, getScheduledSignal, getSizingSchema, getStrategySchema, getSymbol, getTimestamp, getTotalClosed, getTotalCostClosed, getTotalPercentClosed, getWalkerSchema, hasTradeContext, investedCostToPercent, backtest as lib, listExchangeSchema, listFrameSchema, listRiskSchema, listSizingSchema, listStrategySchema, listWalkerSchema, listenActivePing, listenActivePingOnce, listenBacktestProgress, listenBreakevenAvailable, listenBreakevenAvailableOnce, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenPartialLossAvailable, listenPartialLossAvailableOnce, listenPartialProfitAvailable, listenPartialProfitAvailableOnce, listenPerformance, listenRisk, listenRiskOnce, listenSchedulePing, listenSchedulePingOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenStrategyCommit, listenStrategyCommitOnce, listenSync, listenSyncOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, overrideActionSchema, overrideExchangeSchema, overrideFrameSchema, overrideRiskSchema, overrideSizingSchema, overrideStrategySchema, overrideWalkerSchema, parseArgs, percentDiff, percentToCloseCost, percentValue, roundTicks, set, setColumns, setConfig, setLogger, shutdown, slPercentShiftToPrice, slPriceToPercentShift, stopStrategy, toProfitLossDto, tpPercentShiftToPrice, tpPriceToPercentShift, validate, waitForCandle, warmCandles };
|
|
45883
|
+
export { ActionBase, Backtest, Breakeven, Broker, BrokerBase, Cache, Constant, Exchange, ExecutionContextService, Heat, Live, Log, Markdown, MarkdownFileBase, MarkdownFolderBase, MethodContextService, Notification, NotificationBacktest, NotificationLive, Partial, Performance, PersistBase, PersistBreakevenAdapter, PersistCandleAdapter, PersistLogAdapter, PersistMeasureAdapter, PersistNotificationAdapter, PersistPartialAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistSignalAdapter, PersistStorageAdapter, PositionSize, Report, ReportBase, Risk, Schedule, Storage, StorageBacktest, StorageLive, Strategy, Sync, Walker, addActionSchema, addExchangeSchema, addFrameSchema, addRiskSchema, addSizingSchema, addStrategySchema, addWalkerSchema, alignToInterval, checkCandles, commitActivateScheduled, commitAverageBuy, commitBreakeven, commitCancelScheduled, commitClosePending, commitPartialLoss, commitPartialLossCost, commitPartialProfit, commitPartialProfitCost, commitTrailingStop, commitTrailingStopCost, commitTrailingTake, commitTrailingTakeCost, dumpMessages, emitters, formatPrice, formatQuantity, get, getActionSchema, getAggregatedTrades, getAveragePrice, getBacktestTimeframe, getBreakeven, getCandles, getColumns, getConfig, getContext, getDate, getDefaultColumns, getDefaultConfig, getEffectivePriceOpen, getExchangeSchema, getFrameSchema, getMode, getNextCandles, getOrderBook, getPendingSignal, getPositionAveragePrice, getPositionEntryOverlap, getPositionInvestedCost, getPositionInvestedCount, getPositionLevels, getPositionPartialOverlap, getPositionPartials, getPositionPnlCost, getPositionPnlPercent, getRawCandles, getRiskSchema, getScheduledSignal, getSizingSchema, getStrategySchema, getSymbol, getTimestamp, getTotalClosed, getTotalCostClosed, getTotalPercentClosed, getWalkerSchema, hasTradeContext, investedCostToPercent, backtest as lib, listExchangeSchema, listFrameSchema, listRiskSchema, listSizingSchema, listStrategySchema, listWalkerSchema, listenActivePing, listenActivePingOnce, listenBacktestProgress, listenBreakevenAvailable, listenBreakevenAvailableOnce, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenPartialLossAvailable, listenPartialLossAvailableOnce, listenPartialProfitAvailable, listenPartialProfitAvailableOnce, listenPerformance, listenRisk, listenRiskOnce, listenSchedulePing, listenSchedulePingOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenStrategyCommit, listenStrategyCommitOnce, listenSync, listenSyncOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, overrideActionSchema, overrideExchangeSchema, overrideFrameSchema, overrideRiskSchema, overrideSizingSchema, overrideStrategySchema, overrideWalkerSchema, parseArgs, percentDiff, percentToCloseCost, percentValue, roundTicks, set, setColumns, setConfig, setLogger, shutdown, slPercentShiftToPrice, slPriceToPercentShift, stopStrategy, toProfitLossDto, tpPercentShiftToPrice, tpPriceToPercentShift, validate, waitForCandle, warmCandles };
|