@tradejs/core 2.0.18 → 2.0.19
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/dist/backtest.js +2 -3
- package/dist/backtest.mjs +1 -1
- package/dist/{chunk-NN7Z3GIK.mjs → chunk-Q3OFPRVV.mjs} +115 -125
- package/dist/{chunk-BOETNABM.mjs → chunk-S4KHOAXM.mjs} +1 -2
- package/dist/chunk-U3GDILUZ.mjs +13 -0
- package/dist/grid.d.mts +3 -2
- package/dist/grid.d.ts +3 -2
- package/dist/grid.js +13 -11
- package/dist/grid.mjs +6 -6
- package/dist/{indicators-C4AaiFrs.d.ts → indicatorControllerContracts-DdSuUzb2.d.mts} +26 -92
- package/dist/{indicators-C4AaiFrs.d.mts → indicatorControllerContracts-DdSuUzb2.d.ts} +26 -92
- package/dist/indicators.d.mts +70 -3
- package/dist/indicators.d.ts +70 -3
- package/dist/indicators.js +114 -125
- package/dist/indicators.mjs +2 -2
- package/dist/strategies.d.mts +6 -3
- package/dist/strategies.d.ts +6 -3
- package/dist/strategies.js +133 -138
- package/dist/strategies.mjs +9 -6
- package/dist/time.js +2 -3
- package/dist/time.mjs +1 -1
- package/dist/uuid-DMoErO_1.d.mts +3 -0
- package/dist/uuid-DMoErO_1.d.ts +3 -0
- package/package.json +2 -2
- package/dist/chunk-AJK4NS7Y.mjs +0 -10
package/dist/backtest.js
CHANGED
|
@@ -860,14 +860,13 @@ var getFormatted = (stat, key) => {
|
|
|
860
860
|
|
|
861
861
|
// src/utils/timestamp.ts
|
|
862
862
|
var import_date_fns2 = require("date-fns");
|
|
863
|
-
var import_date_fns3 = require("date-fns");
|
|
864
863
|
var TIMELINE_STEP = 864e5;
|
|
865
864
|
var RUNTIME_STORAGE_DAY_OFFSET_MS = 6 * 60 * 60 * 1e3;
|
|
866
865
|
var getTimestamp = (days = 0) => {
|
|
867
866
|
if (days > 0) {
|
|
868
|
-
return (0,
|
|
867
|
+
return (0, import_date_fns2.getUnixTime)((0, import_date_fns2.subDays)(/* @__PURE__ */ new Date(), days)) * 1e3;
|
|
869
868
|
}
|
|
870
|
-
return (0,
|
|
869
|
+
return (0, import_date_fns2.getUnixTime)(/* @__PURE__ */ new Date()) * 1e3;
|
|
871
870
|
};
|
|
872
871
|
var getTimeline = (start = getTimestamp(BACKTEST_DEFAULT_DAYS), end = getTimestamp(), step = TIMELINE_STEP) => {
|
|
873
872
|
const res = new Array();
|
package/dist/backtest.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from "./chunk-M7QGVZ3J.mjs";
|
|
7
7
|
import {
|
|
8
8
|
toMs
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-S4KHOAXM.mjs";
|
|
10
10
|
import {
|
|
11
11
|
CORRELATION_WINDOW,
|
|
12
12
|
ML_BASE_CANDLES_WINDOW,
|
|
@@ -6860,7 +6860,7 @@ var calculateRecentRangeExpansionSeries = (candles, lookback) => calculateRecent
|
|
|
6860
6860
|
(index) => calculateRangeExpansionAt(candles, index)
|
|
6861
6861
|
);
|
|
6862
6862
|
|
|
6863
|
-
// src/utils/
|
|
6863
|
+
// src/utils/indicatorBaseContextRelative.ts
|
|
6864
6864
|
var SESSION_WINDOWS = [
|
|
6865
6865
|
{ name: "asia", startMinuteUtc: 0, endMinuteUtc: 8 * 60 },
|
|
6866
6866
|
{ name: "europe", startMinuteUtc: 7 * 60, endMinuteUtc: 16 * 60 },
|
|
@@ -6869,28 +6869,24 @@ var SESSION_WINDOWS = [
|
|
|
6869
6869
|
var FUNDING_WINDOW_STEP_MINUTES = 8 * 60;
|
|
6870
6870
|
var FUNDING_WINDOW_NEARBY_MINUTES = 60;
|
|
6871
6871
|
var SESSION_WINDOW_EDGE_MINUTES = 60;
|
|
6872
|
-
var BASE_INTERVAL_MS = 15 * 6e4;
|
|
6873
6872
|
var PSYCHOLOGICAL_LEVEL_WINDOWS = {
|
|
6874
|
-
m15:
|
|
6873
|
+
m15: 15 * 6e4,
|
|
6875
6874
|
h1: 60 * 6e4,
|
|
6876
6875
|
h4: 4 * 60 * 6e4
|
|
6877
6876
|
};
|
|
6878
|
-
var isInsideSession = (minuteUtc, startMinuteUtc, endMinuteUtc) => startMinuteUtc <= endMinuteUtc ? minuteUtc >= startMinuteUtc && minuteUtc < endMinuteUtc : minuteUtc >= startMinuteUtc || minuteUtc < endMinuteUtc;
|
|
6879
6877
|
var buildSessionContext = (timestamp) => {
|
|
6880
6878
|
const date = new Date(timestamp);
|
|
6881
|
-
const
|
|
6882
|
-
const utcMinute = date.getUTCMinutes();
|
|
6883
|
-
const minuteUtc = utcHour * 60 + utcMinute;
|
|
6879
|
+
const minuteUtc = date.getUTCHours() * 60 + date.getUTCMinutes();
|
|
6884
6880
|
const dayOfWeekUtc = date.getUTCDay() || 7;
|
|
6885
6881
|
const activeSessions = SESSION_WINDOWS.filter(
|
|
6886
|
-
(
|
|
6887
|
-
).map((
|
|
6882
|
+
({ startMinuteUtc, endMinuteUtc }) => startMinuteUtc <= endMinuteUtc ? minuteUtc >= startMinuteUtc && minuteUtc < endMinuteUtc : minuteUtc >= startMinuteUtc || minuteUtc < endMinuteUtc
|
|
6883
|
+
).map(({ name }) => name);
|
|
6888
6884
|
const sessionPhase = activeSessions.includes("us") ? "us" : activeSessions.includes("europe") ? "europe" : activeSessions.includes("asia") ? "asia" : "off_hours";
|
|
6889
6885
|
const primaryWindow = SESSION_WINDOWS.find(
|
|
6890
|
-
(
|
|
6886
|
+
({ name }) => name === sessionPhase
|
|
6891
6887
|
);
|
|
6892
|
-
const minutesFromSessionOpen = primaryWindow
|
|
6893
|
-
const minutesToSessionClose = primaryWindow
|
|
6888
|
+
const minutesFromSessionOpen = primaryWindow ? minuteUtc - primaryWindow.startMinuteUtc : null;
|
|
6889
|
+
const minutesToSessionClose = primaryWindow ? primaryWindow.endMinuteUtc - minuteUtc : null;
|
|
6894
6890
|
const sessionWindowPhase = primaryWindow == null || minutesFromSessionOpen == null ? "off_hours" : minutesFromSessionOpen < SESSION_WINDOW_EDGE_MINUTES ? "opening" : minutesToSessionClose != null && minutesToSessionClose <= SESSION_WINDOW_EDGE_MINUTES ? "closing" : "active";
|
|
6895
6891
|
const minutesToFundingWindow = (FUNDING_WINDOW_STEP_MINUTES - minuteUtc % FUNDING_WINDOW_STEP_MINUTES) % FUNDING_WINDOW_STEP_MINUTES;
|
|
6896
6892
|
return {
|
|
@@ -6906,7 +6902,7 @@ var buildSessionContext = (timestamp) => {
|
|
|
6906
6902
|
isWeekendUtc: dayOfWeekUtc >= 6
|
|
6907
6903
|
};
|
|
6908
6904
|
};
|
|
6909
|
-
var
|
|
6905
|
+
var unavailablePsychologicalLevelWindow = () => ({
|
|
6910
6906
|
crossed: null,
|
|
6911
6907
|
direction: "unknown",
|
|
6912
6908
|
level: null,
|
|
@@ -6915,7 +6911,7 @@ var buildUnavailablePsychologicalLevelWindow = () => ({
|
|
|
6915
6911
|
});
|
|
6916
6912
|
var buildPsychologicalLevelWindow = (startPrice, endPrice, stepUsd) => {
|
|
6917
6913
|
if (!Number.isFinite(startPrice) || !Number.isFinite(endPrice) || !Number.isFinite(stepUsd) || startPrice <= 0 || endPrice <= 0 || stepUsd <= 0) {
|
|
6918
|
-
return
|
|
6914
|
+
return unavailablePsychologicalLevelWindow();
|
|
6919
6915
|
}
|
|
6920
6916
|
if (endPrice === startPrice) {
|
|
6921
6917
|
return {
|
|
@@ -6939,21 +6935,17 @@ var buildPsychologicalLevelWindow = (startPrice, endPrice, stepUsd) => {
|
|
|
6939
6935
|
distanceBeyondLevelBps: null
|
|
6940
6936
|
};
|
|
6941
6937
|
}
|
|
6942
|
-
const levelsCrossed = Math.round(Math.abs(lastCrossedLevel - firstCrossedLevel) / stepUsd) + 1;
|
|
6943
|
-
const distanceBeyondLevelBps = Math.abs(endPrice - lastCrossedLevel) / lastCrossedLevel * 1e4;
|
|
6944
6938
|
return {
|
|
6945
6939
|
crossed: true,
|
|
6946
6940
|
direction: movingUp ? "up" : "down",
|
|
6947
6941
|
level: lastCrossedLevel,
|
|
6948
|
-
levelsCrossed,
|
|
6949
|
-
distanceBeyondLevelBps
|
|
6942
|
+
levelsCrossed: Math.round(Math.abs(lastCrossedLevel - firstCrossedLevel) / stepUsd) + 1,
|
|
6943
|
+
distanceBeyondLevelBps: Math.abs(endPrice - lastCrossedLevel) / lastCrossedLevel * 1e4
|
|
6950
6944
|
};
|
|
6951
6945
|
};
|
|
6952
6946
|
var buildPsychologicalLevelAssetContext = (candles, stepUsd) => {
|
|
6953
6947
|
const endCandle = candles[candles.length - 1];
|
|
6954
|
-
if (!endCandle)
|
|
6955
|
-
return null;
|
|
6956
|
-
}
|
|
6948
|
+
if (!endCandle) return null;
|
|
6957
6949
|
const candlesByTimestamp = new Map(
|
|
6958
6950
|
candles.map((item) => [item.timestamp, item])
|
|
6959
6951
|
);
|
|
@@ -6968,104 +6960,70 @@ var buildPsychologicalLevelAssetContext = (candles, stepUsd) => {
|
|
|
6968
6960
|
startCandle.close,
|
|
6969
6961
|
endCandle.close,
|
|
6970
6962
|
stepUsd
|
|
6971
|
-
) :
|
|
6963
|
+
) : unavailablePsychologicalLevelWindow()
|
|
6972
6964
|
];
|
|
6973
6965
|
})
|
|
6974
6966
|
);
|
|
6975
|
-
return {
|
|
6976
|
-
source: "aligned_15m_ohlcv",
|
|
6977
|
-
stepUsd,
|
|
6978
|
-
windows
|
|
6979
|
-
};
|
|
6967
|
+
return { source: "aligned_15m_ohlcv", stepUsd, windows };
|
|
6980
6968
|
};
|
|
6981
|
-
var
|
|
6982
|
-
var BASE_CONTEXT_CANDLE_WINDOW = 256;
|
|
6983
|
-
var PIVOT_LEFT_RIGHT = 2;
|
|
6984
|
-
var ZONE_ATR_FACTOR = 0.5;
|
|
6985
|
-
var PROFILE_BIN_COUNT = 24;
|
|
6986
|
-
var SR_ZONE_PIVOT_PERIOD = 9;
|
|
6987
|
-
var SR_ZONE_MIN_STRENGTH = 2;
|
|
6988
|
-
var SR_ZONE_MAX_PIVOTS = 15;
|
|
6989
|
-
var SR_ZONE_CHANNEL_WIDTH_PCT = 8;
|
|
6990
|
-
var SR_ZONE_MAX_LEVELS = 6;
|
|
6991
|
-
var VOLUME_STRUCTURE_CALC_BARS = 180;
|
|
6992
|
-
var VOLUME_STRUCTURE_ROW_COUNT = 20;
|
|
6993
|
-
var LIQUIDITY_ZONE_LOOKBACK = 15;
|
|
6994
|
-
var LIQUIDITY_ZONE_MAX_AGE = 120;
|
|
6995
|
-
var LIQUIDITY_TAIL_ATR_LENGTH = 14;
|
|
6996
|
-
var LIQUIDITY_TAIL_ATR_MULT = 0.8;
|
|
6997
|
-
var LIQUIDITY_TAIL_MIN_WICK_RATIO = 1.3;
|
|
6998
|
-
var LIQUIDITY_TAIL_WICK_DOMINANCE = 1.2;
|
|
6999
|
-
var LIQUIDITY_TAIL_MIN_GAP = 5;
|
|
7000
|
-
var LIQUIDITY_TAIL_MAX_AGE = 120;
|
|
7001
|
-
var TREND_FOLLOW_PIVOT_LENGTH = 10;
|
|
7002
|
-
var TREND_FOLLOW_ATR_LENGTH = 14;
|
|
7003
|
-
var TREND_FOLLOW_ATR_MULT = 4;
|
|
7004
|
-
var ADAPTIVE_CHANNEL_REGRESSION_BARS = 7;
|
|
7005
|
-
var ADAPTIVE_CHANNEL_ENVELOPE_BARS = 2;
|
|
7006
|
-
var ADAPTIVE_CHANNEL_ATR_STRETCH = 2;
|
|
7007
|
-
var ADAPTIVE_CHANNEL_VOLATILITY_LOOKBACK = 100;
|
|
7008
|
-
var ADAPTIVE_CHANNEL_CALC_LOOKBACK = 220;
|
|
7009
|
-
var STRUCTURE_ZONES_ZONE_WIDTH_ATR = 0.5;
|
|
7010
|
-
var STRUCTURE_ZONES_ACCEPT_BARS = 2;
|
|
7011
|
-
var calculateReturnPctFromCandles = (candles) => {
|
|
6969
|
+
var returnPct = (candles) => {
|
|
7012
6970
|
if (candles.length < 2) return null;
|
|
7013
|
-
const previous = candles[candles.length - 2];
|
|
7014
|
-
const current = candles[candles.length - 1];
|
|
7015
|
-
return percentChange(current.close, previous.close);
|
|
7016
|
-
};
|
|
7017
|
-
var calculateRatioReturnPct = (coinCandles, btcCandles) => {
|
|
7018
|
-
if (coinCandles.length < 2 || btcCandles.length < 2) return null;
|
|
7019
|
-
const currentCoin = coinCandles[coinCandles.length - 1];
|
|
7020
|
-
const previousCoin = coinCandles[coinCandles.length - 2];
|
|
7021
|
-
const currentBtc = btcCandles[btcCandles.length - 1];
|
|
7022
|
-
const previousBtc = btcCandles[btcCandles.length - 2];
|
|
7023
|
-
if (currentBtc.close <= 0 || previousBtc.close <= 0) return null;
|
|
7024
6971
|
return percentChange(
|
|
7025
|
-
|
|
7026
|
-
|
|
6972
|
+
candles[candles.length - 1].close,
|
|
6973
|
+
candles[candles.length - 2].close
|
|
7027
6974
|
);
|
|
7028
6975
|
};
|
|
7029
|
-
var
|
|
7030
|
-
|
|
7031
|
-
const
|
|
7032
|
-
|
|
7033
|
-
|
|
7034
|
-
|
|
7035
|
-
|
|
7036
|
-
|
|
7037
|
-
|
|
7038
|
-
|
|
7039
|
-
|
|
7040
|
-
|
|
7041
|
-
|
|
7042
|
-
|
|
7043
|
-
|
|
6976
|
+
var ratioReturnPct = (target, reference) => {
|
|
6977
|
+
if (target.length < 2 || reference.length < 2) return null;
|
|
6978
|
+
const targetCurrent = target[target.length - 1];
|
|
6979
|
+
const targetPrevious = target[target.length - 2];
|
|
6980
|
+
const referenceCurrent = reference[reference.length - 1];
|
|
6981
|
+
const referencePrevious = reference[reference.length - 2];
|
|
6982
|
+
if (referenceCurrent.close <= 0 || referencePrevious.close <= 0) return null;
|
|
6983
|
+
return percentChange(
|
|
6984
|
+
targetCurrent.close / referenceCurrent.close,
|
|
6985
|
+
targetPrevious.close / referencePrevious.close
|
|
6986
|
+
);
|
|
6987
|
+
};
|
|
6988
|
+
var alignRecentCandles = (target, reference) => {
|
|
6989
|
+
const alignedTarget = [];
|
|
6990
|
+
const alignedReference = [];
|
|
6991
|
+
let targetIndex = Math.max(0, target.length - 80);
|
|
6992
|
+
let referenceIndex = Math.max(0, reference.length - 80);
|
|
6993
|
+
while (targetIndex < target.length && referenceIndex < reference.length) {
|
|
6994
|
+
const targetTimestamp = target[targetIndex].timestamp;
|
|
6995
|
+
const referenceTimestamp = reference[referenceIndex].timestamp;
|
|
6996
|
+
if (targetTimestamp === referenceTimestamp) {
|
|
6997
|
+
alignedTarget.push(target[targetIndex]);
|
|
6998
|
+
alignedReference.push(reference[referenceIndex]);
|
|
6999
|
+
targetIndex += 1;
|
|
7000
|
+
referenceIndex += 1;
|
|
7001
|
+
} else if (targetTimestamp < referenceTimestamp) {
|
|
7002
|
+
targetIndex += 1;
|
|
7044
7003
|
} else {
|
|
7045
|
-
|
|
7004
|
+
referenceIndex += 1;
|
|
7046
7005
|
}
|
|
7047
7006
|
}
|
|
7048
|
-
return {
|
|
7007
|
+
return { alignedTarget, alignedReference };
|
|
7049
7008
|
};
|
|
7050
|
-
var
|
|
7009
|
+
var returnSeries = (candles, limit) => {
|
|
7051
7010
|
const returns = [];
|
|
7052
|
-
|
|
7053
|
-
for (let index = startIndex; index < candles.length; index += 1) {
|
|
7011
|
+
for (let index = Math.max(1, candles.length - limit); index < candles.length; index += 1) {
|
|
7054
7012
|
const previous = candles[index - 1];
|
|
7055
7013
|
const current = candles[index];
|
|
7056
7014
|
if (previous.close <= 0) continue;
|
|
7057
|
-
const
|
|
7058
|
-
if (
|
|
7015
|
+
const value = percentChange(current.close, previous.close);
|
|
7016
|
+
if (value != null && Number.isFinite(value)) returns.push(value);
|
|
7059
7017
|
}
|
|
7060
7018
|
return returns;
|
|
7061
7019
|
};
|
|
7062
|
-
var
|
|
7020
|
+
var beta = (targetReturns, referenceReturns) => {
|
|
7063
7021
|
const length = Math.min(targetReturns.length, referenceReturns.length);
|
|
7064
7022
|
if (length < 2) return null;
|
|
7065
7023
|
const target = targetReturns.slice(-length);
|
|
7066
7024
|
const reference = referenceReturns.slice(-length);
|
|
7067
|
-
const referenceMean = reference.reduce((sum2, value) => sum2 + value, 0) /
|
|
7068
|
-
const targetMean = target.reduce((sum2, value) => sum2 + value, 0) /
|
|
7025
|
+
const referenceMean = reference.reduce((sum2, value) => sum2 + value, 0) / length;
|
|
7026
|
+
const targetMean = target.reduce((sum2, value) => sum2 + value, 0) / length;
|
|
7069
7027
|
let covariance = 0;
|
|
7070
7028
|
let referenceVariance = 0;
|
|
7071
7029
|
for (let index = 0; index < length; index += 1) {
|
|
@@ -7082,16 +7040,6 @@ var classifyRatioTrend = (ratioReturn24h, ratioReturn4h) => {
|
|
|
7082
7040
|
if (value < -0.15) return "down";
|
|
7083
7041
|
return "flat";
|
|
7084
7042
|
};
|
|
7085
|
-
var hasDistinctReferenceCandles = (coinCandles, referenceCandles) => {
|
|
7086
|
-
const coinLast = coinCandles[coinCandles.length - 1];
|
|
7087
|
-
const referenceLast = referenceCandles[referenceCandles.length - 1];
|
|
7088
|
-
const coinPrev = coinCandles[coinCandles.length - 2];
|
|
7089
|
-
const referencePrev = referenceCandles[referenceCandles.length - 2];
|
|
7090
|
-
if (!coinLast || !referenceLast || !coinPrev || !referencePrev) {
|
|
7091
|
-
return false;
|
|
7092
|
-
}
|
|
7093
|
-
return coinLast.timestamp !== referenceLast.timestamp || coinLast.close !== referenceLast.close || coinPrev.timestamp !== referencePrev.timestamp || coinPrev.close !== referencePrev.close;
|
|
7094
|
-
};
|
|
7095
7043
|
var buildTargetVsBtcContext = ({
|
|
7096
7044
|
coin1h,
|
|
7097
7045
|
btc1h,
|
|
@@ -7102,19 +7050,21 @@ var buildTargetVsBtcContext = ({
|
|
|
7102
7050
|
coinCandles,
|
|
7103
7051
|
btcCandles
|
|
7104
7052
|
}) => {
|
|
7105
|
-
const ratioReturn1h =
|
|
7106
|
-
const ratioReturn4h =
|
|
7107
|
-
const ratioReturn24h =
|
|
7108
|
-
const coinReturn1h =
|
|
7109
|
-
const coinReturn4h =
|
|
7110
|
-
const coinReturn24h =
|
|
7111
|
-
const btcReturn1h =
|
|
7112
|
-
const btcReturn4h =
|
|
7113
|
-
const btcReturn24h =
|
|
7114
|
-
const {
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
7053
|
+
const ratioReturn1h = ratioReturnPct(coin1h, btc1h);
|
|
7054
|
+
const ratioReturn4h = ratioReturnPct(coin4h, btc4h);
|
|
7055
|
+
const ratioReturn24h = ratioReturnPct(coin1d, btc1d);
|
|
7056
|
+
const coinReturn1h = returnPct(coin1h);
|
|
7057
|
+
const coinReturn4h = returnPct(coin4h);
|
|
7058
|
+
const coinReturn24h = returnPct(coin1d);
|
|
7059
|
+
const btcReturn1h = returnPct(btc1h);
|
|
7060
|
+
const btcReturn4h = returnPct(btc4h);
|
|
7061
|
+
const btcReturn24h = returnPct(btc1d);
|
|
7062
|
+
const { alignedTarget, alignedReference } = alignRecentCandles(
|
|
7063
|
+
coinCandles,
|
|
7064
|
+
btcCandles
|
|
7065
|
+
);
|
|
7066
|
+
const coinReturns20 = returnSeries(alignedTarget, 21).slice(-20);
|
|
7067
|
+
const btcReturns20 = returnSeries(alignedReference, 21).slice(-20);
|
|
7118
7068
|
return {
|
|
7119
7069
|
source: "aligned_ohlcv",
|
|
7120
7070
|
ratioReturn1h,
|
|
@@ -7123,11 +7073,21 @@ var buildTargetVsBtcContext = ({
|
|
|
7123
7073
|
alphaVsBtc1h: coinReturn1h == null || btcReturn1h == null ? null : coinReturn1h - btcReturn1h,
|
|
7124
7074
|
alphaVsBtc4h: coinReturn4h == null || btcReturn4h == null ? null : coinReturn4h - btcReturn4h,
|
|
7125
7075
|
alphaVsBtc24h: coinReturn24h == null || btcReturn24h == null ? null : coinReturn24h - btcReturn24h,
|
|
7126
|
-
betaToBtc20:
|
|
7127
|
-
correlationToBtc20,
|
|
7076
|
+
betaToBtc20: beta(coinReturns20, btcReturns20),
|
|
7077
|
+
correlationToBtc20: coinReturns20.length === btcReturns20.length && coinReturns20.length >= 2 ? calculatePearsonCorrelation(coinReturns20, btcReturns20) : null,
|
|
7128
7078
|
ratioTrend: classifyRatioTrend(ratioReturn24h, ratioReturn4h)
|
|
7129
7079
|
};
|
|
7130
7080
|
};
|
|
7081
|
+
var hasDistinctReferenceCandles = (target, reference) => {
|
|
7082
|
+
const targetLast = target[target.length - 1];
|
|
7083
|
+
const referenceLast = reference[reference.length - 1];
|
|
7084
|
+
const targetPrevious = target[target.length - 2];
|
|
7085
|
+
const referencePrevious = reference[reference.length - 2];
|
|
7086
|
+
if (!targetLast || !referenceLast || !targetPrevious || !referencePrevious) {
|
|
7087
|
+
return false;
|
|
7088
|
+
}
|
|
7089
|
+
return targetLast.timestamp !== referenceLast.timestamp || targetLast.close !== referenceLast.close || targetPrevious.timestamp !== referencePrevious.timestamp || targetPrevious.close !== referencePrevious.close;
|
|
7090
|
+
};
|
|
7131
7091
|
var buildTargetVsEthContext = ({
|
|
7132
7092
|
coin1h,
|
|
7133
7093
|
eth1h,
|
|
@@ -7138,9 +7098,7 @@ var buildTargetVsEthContext = ({
|
|
|
7138
7098
|
coinCandles,
|
|
7139
7099
|
ethCandles
|
|
7140
7100
|
}) => {
|
|
7141
|
-
if (!hasDistinctReferenceCandles(coinCandles, ethCandles))
|
|
7142
|
-
return null;
|
|
7143
|
-
}
|
|
7101
|
+
if (!hasDistinctReferenceCandles(coinCandles, ethCandles)) return null;
|
|
7144
7102
|
const context = buildTargetVsBtcContext({
|
|
7145
7103
|
coin1h,
|
|
7146
7104
|
btc1h: eth1h,
|
|
@@ -7164,6 +7122,38 @@ var buildTargetVsEthContext = ({
|
|
|
7164
7122
|
ratioTrend: context.ratioTrend
|
|
7165
7123
|
};
|
|
7166
7124
|
};
|
|
7125
|
+
|
|
7126
|
+
// src/utils/indicatorBaseContext.ts
|
|
7127
|
+
var STRUCTURE_LOOKBACK = 80;
|
|
7128
|
+
var BASE_CONTEXT_CANDLE_WINDOW = 256;
|
|
7129
|
+
var PIVOT_LEFT_RIGHT = 2;
|
|
7130
|
+
var ZONE_ATR_FACTOR = 0.5;
|
|
7131
|
+
var PROFILE_BIN_COUNT = 24;
|
|
7132
|
+
var SR_ZONE_PIVOT_PERIOD = 9;
|
|
7133
|
+
var SR_ZONE_MIN_STRENGTH = 2;
|
|
7134
|
+
var SR_ZONE_MAX_PIVOTS = 15;
|
|
7135
|
+
var SR_ZONE_CHANNEL_WIDTH_PCT = 8;
|
|
7136
|
+
var SR_ZONE_MAX_LEVELS = 6;
|
|
7137
|
+
var VOLUME_STRUCTURE_CALC_BARS = 180;
|
|
7138
|
+
var VOLUME_STRUCTURE_ROW_COUNT = 20;
|
|
7139
|
+
var LIQUIDITY_ZONE_LOOKBACK = 15;
|
|
7140
|
+
var LIQUIDITY_ZONE_MAX_AGE = 120;
|
|
7141
|
+
var LIQUIDITY_TAIL_ATR_LENGTH = 14;
|
|
7142
|
+
var LIQUIDITY_TAIL_ATR_MULT = 0.8;
|
|
7143
|
+
var LIQUIDITY_TAIL_MIN_WICK_RATIO = 1.3;
|
|
7144
|
+
var LIQUIDITY_TAIL_WICK_DOMINANCE = 1.2;
|
|
7145
|
+
var LIQUIDITY_TAIL_MIN_GAP = 5;
|
|
7146
|
+
var LIQUIDITY_TAIL_MAX_AGE = 120;
|
|
7147
|
+
var TREND_FOLLOW_PIVOT_LENGTH = 10;
|
|
7148
|
+
var TREND_FOLLOW_ATR_LENGTH = 14;
|
|
7149
|
+
var TREND_FOLLOW_ATR_MULT = 4;
|
|
7150
|
+
var ADAPTIVE_CHANNEL_REGRESSION_BARS = 7;
|
|
7151
|
+
var ADAPTIVE_CHANNEL_ENVELOPE_BARS = 2;
|
|
7152
|
+
var ADAPTIVE_CHANNEL_ATR_STRETCH = 2;
|
|
7153
|
+
var ADAPTIVE_CHANNEL_VOLATILITY_LOOKBACK = 100;
|
|
7154
|
+
var ADAPTIVE_CHANNEL_CALC_LOOKBACK = 220;
|
|
7155
|
+
var STRUCTURE_ZONES_ZONE_WIDTH_ATR = 0.5;
|
|
7156
|
+
var STRUCTURE_ZONES_ACCEPT_BARS = 2;
|
|
7167
7157
|
var BASE_CONTEXT_MA_LAYER_PERIODS = [
|
|
7168
7158
|
[5, 12],
|
|
7169
7159
|
[9, 13],
|
|
@@ -4,8 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-MKCQSB4H.mjs";
|
|
5
5
|
|
|
6
6
|
// src/utils/timestamp.ts
|
|
7
|
-
import { format } from "date-fns";
|
|
8
|
-
import { getUnixTime, subDays } from "date-fns";
|
|
7
|
+
import { format, getUnixTime, subDays } from "date-fns";
|
|
9
8
|
var TIMELINE_STEP = 864e5;
|
|
10
9
|
var DAY_MS = 864e5;
|
|
11
10
|
var RUNTIME_STORAGE_DAY_OFFSET_MS = 6 * 60 * 60 * 1e3;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// src/utils/uuid.ts
|
|
2
|
+
var randomUuid = () => {
|
|
3
|
+
if (!globalThis.crypto?.randomUUID) {
|
|
4
|
+
throw new Error("crypto.randomUUID is not available in this runtime");
|
|
5
|
+
}
|
|
6
|
+
return globalThis.crypto.randomUUID();
|
|
7
|
+
};
|
|
8
|
+
var createIdGenerator = (generateUuid = randomUuid) => (length = 12) => generateUuid().slice(-length);
|
|
9
|
+
var uuid = createIdGenerator();
|
|
10
|
+
|
|
11
|
+
export {
|
|
12
|
+
uuid
|
|
13
|
+
};
|
package/dist/grid.d.mts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { StrategyConfigGrid, Interval, TestSuite, StrategyConfig } from '@tradejs/types';
|
|
2
|
+
import { I as IdGenerator } from './uuid-DMoErO_1.mjs';
|
|
2
3
|
|
|
3
4
|
type GenericConfig = StrategyConfig;
|
|
4
5
|
declare const generateParamGrid: <T extends StrategyConfig>(paramOptions: StrategyConfigGrid) => T[];
|
|
5
|
-
declare const generateName: (prefix: string) => string;
|
|
6
|
+
declare const generateName: (prefix: string, generateId?: IdGenerator) => string;
|
|
6
7
|
declare const mergeConfigs: (configs: GenericConfig[]) => Record<string, unknown[]>;
|
|
7
|
-
declare const createTestSuite: (userName: string, tickers: string[], strategyName: string, backtestConfig: StrategyConfigGrid, connectorName: string, interval?: Interval) => TestSuite;
|
|
8
|
+
declare const createTestSuite: (userName: string, tickers: string[], strategyName: string, backtestConfig: StrategyConfigGrid, connectorName: string, interval?: Interval, generateId?: IdGenerator) => TestSuite;
|
|
8
9
|
|
|
9
10
|
export { createTestSuite, generateName, generateParamGrid, mergeConfigs };
|
package/dist/grid.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { StrategyConfigGrid, Interval, TestSuite, StrategyConfig } from '@tradejs/types';
|
|
2
|
+
import { I as IdGenerator } from './uuid-DMoErO_1.js';
|
|
2
3
|
|
|
3
4
|
type GenericConfig = StrategyConfig;
|
|
4
5
|
declare const generateParamGrid: <T extends StrategyConfig>(paramOptions: StrategyConfigGrid) => T[];
|
|
5
|
-
declare const generateName: (prefix: string) => string;
|
|
6
|
+
declare const generateName: (prefix: string, generateId?: IdGenerator) => string;
|
|
6
7
|
declare const mergeConfigs: (configs: GenericConfig[]) => Record<string, unknown[]>;
|
|
7
|
-
declare const createTestSuite: (userName: string, tickers: string[], strategyName: string, backtestConfig: StrategyConfigGrid, connectorName: string, interval?: Interval) => TestSuite;
|
|
8
|
+
declare const createTestSuite: (userName: string, tickers: string[], strategyName: string, backtestConfig: StrategyConfigGrid, connectorName: string, interval?: Interval, generateId?: IdGenerator) => TestSuite;
|
|
8
9
|
|
|
9
10
|
export { createTestSuite, generateName, generateParamGrid, mergeConfigs };
|
package/dist/grid.js
CHANGED
|
@@ -60,13 +60,12 @@ var DERIVATIVES_CONTEXT_REFERENCE_SYMBOLS = [
|
|
|
60
60
|
|
|
61
61
|
// src/utils/timestamp.ts
|
|
62
62
|
var import_date_fns = require("date-fns");
|
|
63
|
-
var import_date_fns2 = require("date-fns");
|
|
64
63
|
var RUNTIME_STORAGE_DAY_OFFSET_MS = 6 * 60 * 60 * 1e3;
|
|
65
64
|
var getTimestamp = (days = 0) => {
|
|
66
65
|
if (days > 0) {
|
|
67
|
-
return (0,
|
|
66
|
+
return (0, import_date_fns.getUnixTime)((0, import_date_fns.subDays)(/* @__PURE__ */ new Date(), days)) * 1e3;
|
|
68
67
|
}
|
|
69
|
-
return (0,
|
|
68
|
+
return (0, import_date_fns.getUnixTime)(/* @__PURE__ */ new Date()) * 1e3;
|
|
70
69
|
};
|
|
71
70
|
|
|
72
71
|
// src/utils/toJson.ts
|
|
@@ -75,11 +74,14 @@ var toJson = (data, stringify = false) => {
|
|
|
75
74
|
};
|
|
76
75
|
|
|
77
76
|
// src/utils/uuid.ts
|
|
78
|
-
var
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
77
|
+
var randomUuid = () => {
|
|
78
|
+
if (!globalThis.crypto?.randomUUID) {
|
|
79
|
+
throw new Error("crypto.randomUUID is not available in this runtime");
|
|
80
|
+
}
|
|
81
|
+
return globalThis.crypto.randomUUID();
|
|
82
82
|
};
|
|
83
|
+
var createIdGenerator = (generateUuid = randomUuid) => (length = 12) => generateUuid().slice(-length);
|
|
84
|
+
var uuid = createIdGenerator();
|
|
83
85
|
|
|
84
86
|
// src/utils/grid.ts
|
|
85
87
|
var generateParamGrid = (paramOptions) => {
|
|
@@ -102,7 +104,7 @@ var generateParamGrid = (paramOptions) => {
|
|
|
102
104
|
helper();
|
|
103
105
|
return combinations;
|
|
104
106
|
};
|
|
105
|
-
var generateName = (prefix) => `${prefix}_${
|
|
107
|
+
var generateName = (prefix, generateId = uuid) => `${prefix}_${generateId(6)}`;
|
|
106
108
|
var toBase36Hash = (value) => {
|
|
107
109
|
let hash = 0;
|
|
108
110
|
for (let index = 0; index < value.length; index += 1) {
|
|
@@ -134,14 +136,14 @@ var mergeConfigs = (configs) => {
|
|
|
134
136
|
}
|
|
135
137
|
return result;
|
|
136
138
|
};
|
|
137
|
-
var createTestSuite = (userName, tickers, strategyName, backtestConfig, connectorName, interval = "15") => {
|
|
139
|
+
var createTestSuite = (userName, tickers, strategyName, backtestConfig, connectorName, interval = "15", generateId = uuid) => {
|
|
138
140
|
const start = getTimestamp(BACKTEST_DEFAULT_DAYS);
|
|
139
141
|
const end = getTimestamp();
|
|
140
|
-
const testSuiteId =
|
|
142
|
+
const testSuiteId = generateId(6);
|
|
141
143
|
const paramGrid = generateParamGrid(backtestConfig);
|
|
142
144
|
return tickers.flatMap(
|
|
143
145
|
(symbol) => paramGrid.map((params) => {
|
|
144
|
-
const testId =
|
|
146
|
+
const testId = generateId(6);
|
|
145
147
|
const configId = buildConfigTestId(params);
|
|
146
148
|
return {
|
|
147
149
|
userName,
|
package/dist/grid.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
uuid
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-U3GDILUZ.mjs";
|
|
4
4
|
import {
|
|
5
5
|
getTimestamp
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-S4KHOAXM.mjs";
|
|
7
7
|
import {
|
|
8
8
|
BACKTEST_DEFAULT_DAYS
|
|
9
9
|
} from "./chunk-MKCQSB4H.mjs";
|
|
@@ -33,7 +33,7 @@ var generateParamGrid = (paramOptions) => {
|
|
|
33
33
|
helper();
|
|
34
34
|
return combinations;
|
|
35
35
|
};
|
|
36
|
-
var generateName = (prefix) => `${prefix}_${
|
|
36
|
+
var generateName = (prefix, generateId = uuid) => `${prefix}_${generateId(6)}`;
|
|
37
37
|
var toBase36Hash = (value) => {
|
|
38
38
|
let hash = 0;
|
|
39
39
|
for (let index = 0; index < value.length; index += 1) {
|
|
@@ -65,14 +65,14 @@ var mergeConfigs = (configs) => {
|
|
|
65
65
|
}
|
|
66
66
|
return result;
|
|
67
67
|
};
|
|
68
|
-
var createTestSuite = (userName, tickers, strategyName, backtestConfig, connectorName, interval = "15") => {
|
|
68
|
+
var createTestSuite = (userName, tickers, strategyName, backtestConfig, connectorName, interval = "15", generateId = uuid) => {
|
|
69
69
|
const start = getTimestamp(BACKTEST_DEFAULT_DAYS);
|
|
70
70
|
const end = getTimestamp();
|
|
71
|
-
const testSuiteId =
|
|
71
|
+
const testSuiteId = generateId(6);
|
|
72
72
|
const paramGrid = generateParamGrid(backtestConfig);
|
|
73
73
|
return tickers.flatMap(
|
|
74
74
|
(symbol) => paramGrid.map((params) => {
|
|
75
|
-
const testId =
|
|
75
|
+
const testId = generateId(6);
|
|
76
76
|
const configId = buildConfigTestId(params);
|
|
77
77
|
return {
|
|
78
78
|
userName,
|