@backtest-kit/sidekick 9.6.0 → 9.7.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/README.md +173 -173
- package/content/config/source/timeframe_15m.pine +113 -113
- package/content/config/source/timeframe_4h.pine +56 -56
- package/content/config/symbol.config.cjs +460 -460
- package/content/docker/ollama/docker-compose.yaml +34 -34
- package/content/docker/ollama/watch.sh +2 -2
- package/content/scripts/cache/cache_candles.mjs +47 -47
- package/content/scripts/cache/cache_model.mjs +42 -42
- package/content/scripts/cache/validate_candles.mjs +46 -46
- package/content/scripts/run_timeframe_15m.mjs +77 -77
- package/content/scripts/run_timeframe_4h.mjs +68 -68
- package/package.json +68 -68
- package/scripts/init.mjs +304 -304
- package/src/classes/BacktestLowerStopOnBreakevenAction.mjs +17 -17
- package/src/classes/BacktestPartialProfitTakingAction.mjs +24 -24
- package/src/classes/BacktestPositionMonitorAction.mjs +57 -57
- package/src/config/ccxt.mjs +15 -15
- package/src/config/params.mjs +1 -1
- package/src/config/setup.mjs +45 -45
- package/src/config/validate.mjs +14 -14
- package/src/enum/ActionName.mjs +5 -5
- package/src/enum/ExchangeName.mjs +3 -3
- package/src/enum/FrameName.mjs +6 -6
- package/src/enum/RiskName.mjs +4 -4
- package/src/enum/StrategyName.mjs +3 -3
- package/src/index.mjs +6 -6
- package/src/logic/action/backtest_lower_stop_on_breakeven.action.mjs +9 -9
- package/src/logic/action/backtest_partial_profit_taking.action.mjs +9 -9
- package/src/logic/action/backtest_position_monitor.action.mjs +9 -9
- package/src/logic/exchange/binance.exchange.mjs +69 -69
- package/src/logic/frame/dec_2025.frame.mjs +10 -10
- package/src/logic/frame/feb_2024.frame.mjs +10 -10
- package/src/logic/frame/nov_2025.frame.mjs +10 -10
- package/src/logic/frame/oct_2025.frame.mjs +10 -10
- package/src/logic/index.mjs +15 -15
- package/src/logic/risk/sl_distance.risk.mjs +32 -32
- package/src/logic/risk/tp_distance.risk.mjs +32 -32
- package/src/logic/strategy/main.strategy.mjs +48 -48
- package/src/main/bootstrap.mjs +52 -52
- package/src/math/timeframe_15m.math.mjs +68 -68
- package/src/math/timeframe_4h.math.mjs +53 -53
- package/src/utils/getArgs.mjs +17 -17
- package/template/CLAUDE.mustache +421 -421
- package/template/README.mustache +257 -257
- package/template/env.mustache +2 -2
- package/template/gitignore.mustache +29 -29
- package/template/jsconfig.json.mustache +26 -26
- package/template/package.mustache +37 -37
- package/template/types.mustache +11 -11
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { addFrameSchema } from "backtest-kit";
|
|
2
|
-
import FrameName from "../../enum/FrameName.mjs";
|
|
3
|
-
|
|
4
|
-
addFrameSchema({
|
|
5
|
-
frameName: FrameName.October2025,
|
|
6
|
-
interval: "1m",
|
|
7
|
-
startDate: new Date("2025-10-01T00:00:00Z"),
|
|
8
|
-
endDate: new Date("2025-10-31T23:59:59Z"),
|
|
9
|
-
note: "Sharp market drop from the 9th to 11th",
|
|
10
|
-
});
|
|
1
|
+
import { addFrameSchema } from "backtest-kit";
|
|
2
|
+
import FrameName from "../../enum/FrameName.mjs";
|
|
3
|
+
|
|
4
|
+
addFrameSchema({
|
|
5
|
+
frameName: FrameName.October2025,
|
|
6
|
+
interval: "1m",
|
|
7
|
+
startDate: new Date("2025-10-01T00:00:00Z"),
|
|
8
|
+
endDate: new Date("2025-10-31T23:59:59Z"),
|
|
9
|
+
note: "Sharp market drop from the 9th to 11th",
|
|
10
|
+
});
|
package/src/logic/index.mjs
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import "./exchange/binance.exchange.mjs";
|
|
2
|
-
|
|
3
|
-
import "./action/backtest_partial_profit_taking.action.mjs";
|
|
4
|
-
import "./action/backtest_lower_stop_on_breakeven.action.mjs";
|
|
5
|
-
import "./action/backtest_position_monitor.action.mjs";
|
|
6
|
-
|
|
7
|
-
import "./frame/dec_2025.frame.mjs";
|
|
8
|
-
import "./frame/nov_2025.frame.mjs";
|
|
9
|
-
import "./frame/oct_2025.frame.mjs";
|
|
10
|
-
import "./frame/feb_2024.frame.mjs";
|
|
11
|
-
|
|
12
|
-
import "./risk/sl_distance.risk.mjs";
|
|
13
|
-
import "./risk/tp_distance.risk.mjs";
|
|
14
|
-
|
|
15
|
-
import "./strategy/main.strategy.mjs";
|
|
1
|
+
import "./exchange/binance.exchange.mjs";
|
|
2
|
+
|
|
3
|
+
import "./action/backtest_partial_profit_taking.action.mjs";
|
|
4
|
+
import "./action/backtest_lower_stop_on_breakeven.action.mjs";
|
|
5
|
+
import "./action/backtest_position_monitor.action.mjs";
|
|
6
|
+
|
|
7
|
+
import "./frame/dec_2025.frame.mjs";
|
|
8
|
+
import "./frame/nov_2025.frame.mjs";
|
|
9
|
+
import "./frame/oct_2025.frame.mjs";
|
|
10
|
+
import "./frame/feb_2024.frame.mjs";
|
|
11
|
+
|
|
12
|
+
import "./risk/sl_distance.risk.mjs";
|
|
13
|
+
import "./risk/tp_distance.risk.mjs";
|
|
14
|
+
|
|
15
|
+
import "./strategy/main.strategy.mjs";
|
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
import { addRiskSchema } from "backtest-kit";
|
|
2
|
-
import RiskName from "../../enum/RiskName.mjs";
|
|
3
|
-
|
|
4
|
-
const SLIPPAGE_THRESHOLD = 0.2;
|
|
5
|
-
|
|
6
|
-
addRiskSchema({
|
|
7
|
-
riskName: RiskName.StopLossDistanceRisk,
|
|
8
|
-
validations: [
|
|
9
|
-
{
|
|
10
|
-
validate: ({ currentSignal, currentPrice }) => {
|
|
11
|
-
const {
|
|
12
|
-
priceOpen = currentPrice,
|
|
13
|
-
priceStopLoss,
|
|
14
|
-
position,
|
|
15
|
-
} = currentSignal;
|
|
16
|
-
if (!priceOpen) {
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
// Calculate SL distance percentage
|
|
20
|
-
const slDistance =
|
|
21
|
-
position === "long"
|
|
22
|
-
? ((priceOpen - priceStopLoss) / priceOpen) * 100
|
|
23
|
-
: ((priceStopLoss - priceOpen) / priceOpen) * 100;
|
|
24
|
-
|
|
25
|
-
if (slDistance < SLIPPAGE_THRESHOLD) {
|
|
26
|
-
throw new Error(`SL distance ${slDistance.toFixed(2)}% < 1%`);
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
note: "SL distance must be at least 1%",
|
|
30
|
-
},
|
|
31
|
-
],
|
|
32
|
-
});
|
|
1
|
+
import { addRiskSchema } from "backtest-kit";
|
|
2
|
+
import RiskName from "../../enum/RiskName.mjs";
|
|
3
|
+
|
|
4
|
+
const SLIPPAGE_THRESHOLD = 0.2;
|
|
5
|
+
|
|
6
|
+
addRiskSchema({
|
|
7
|
+
riskName: RiskName.StopLossDistanceRisk,
|
|
8
|
+
validations: [
|
|
9
|
+
{
|
|
10
|
+
validate: ({ currentSignal, currentPrice }) => {
|
|
11
|
+
const {
|
|
12
|
+
priceOpen = currentPrice,
|
|
13
|
+
priceStopLoss,
|
|
14
|
+
position,
|
|
15
|
+
} = currentSignal;
|
|
16
|
+
if (!priceOpen) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
// Calculate SL distance percentage
|
|
20
|
+
const slDistance =
|
|
21
|
+
position === "long"
|
|
22
|
+
? ((priceOpen - priceStopLoss) / priceOpen) * 100
|
|
23
|
+
: ((priceStopLoss - priceOpen) / priceOpen) * 100;
|
|
24
|
+
|
|
25
|
+
if (slDistance < SLIPPAGE_THRESHOLD) {
|
|
26
|
+
throw new Error(`SL distance ${slDistance.toFixed(2)}% < 1%`);
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
note: "SL distance must be at least 1%",
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
});
|
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
import { addRiskSchema } from "backtest-kit";
|
|
2
|
-
import RiskName from "../../enum/RiskName.mjs";
|
|
3
|
-
|
|
4
|
-
const SLIPPAGE_THRESHOLD = 0.2;
|
|
5
|
-
|
|
6
|
-
addRiskSchema({
|
|
7
|
-
riskName: RiskName.TakeProfitDistanceRisk,
|
|
8
|
-
validations: [
|
|
9
|
-
{
|
|
10
|
-
validate: ({ currentSignal, currentPrice }) => {
|
|
11
|
-
const {
|
|
12
|
-
priceOpen = currentPrice,
|
|
13
|
-
priceTakeProfit,
|
|
14
|
-
position,
|
|
15
|
-
} = currentSignal;
|
|
16
|
-
if (!priceOpen) {
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
// Calculate TP distance percentage
|
|
20
|
-
const tpDistance =
|
|
21
|
-
position === "long"
|
|
22
|
-
? ((priceTakeProfit - priceOpen) / priceOpen) * 100
|
|
23
|
-
: ((priceOpen - priceTakeProfit) / priceOpen) * 100;
|
|
24
|
-
|
|
25
|
-
if (tpDistance < SLIPPAGE_THRESHOLD) {
|
|
26
|
-
throw new Error(`TP distance ${tpDistance.toFixed(2)}% < 1%`);
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
note: "TP distance must be at least 1%",
|
|
30
|
-
},
|
|
31
|
-
],
|
|
32
|
-
});
|
|
1
|
+
import { addRiskSchema } from "backtest-kit";
|
|
2
|
+
import RiskName from "../../enum/RiskName.mjs";
|
|
3
|
+
|
|
4
|
+
const SLIPPAGE_THRESHOLD = 0.2;
|
|
5
|
+
|
|
6
|
+
addRiskSchema({
|
|
7
|
+
riskName: RiskName.TakeProfitDistanceRisk,
|
|
8
|
+
validations: [
|
|
9
|
+
{
|
|
10
|
+
validate: ({ currentSignal, currentPrice }) => {
|
|
11
|
+
const {
|
|
12
|
+
priceOpen = currentPrice,
|
|
13
|
+
priceTakeProfit,
|
|
14
|
+
position,
|
|
15
|
+
} = currentSignal;
|
|
16
|
+
if (!priceOpen) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
// Calculate TP distance percentage
|
|
20
|
+
const tpDistance =
|
|
21
|
+
position === "long"
|
|
22
|
+
? ((priceTakeProfit - priceOpen) / priceOpen) * 100
|
|
23
|
+
: ((priceOpen - priceTakeProfit) / priceOpen) * 100;
|
|
24
|
+
|
|
25
|
+
if (tpDistance < SLIPPAGE_THRESHOLD) {
|
|
26
|
+
throw new Error(`TP distance ${tpDistance.toFixed(2)}% < 1%`);
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
note: "TP distance must be at least 1%",
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
});
|
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
import { addStrategySchema } from "backtest-kit";
|
|
2
|
-
import { randomString } from "functools-kit";
|
|
3
|
-
|
|
4
|
-
import * as math_15m from "../../math/timeframe_15m.math.mjs";
|
|
5
|
-
import * as math_4h from "../../math/timeframe_4h.math.mjs";
|
|
6
|
-
|
|
7
|
-
import StrategyName from "../../enum/StrategyName.mjs";
|
|
8
|
-
import RiskName from "../../enum/RiskName.mjs";
|
|
9
|
-
|
|
10
|
-
addStrategySchema({
|
|
11
|
-
strategyName: StrategyName.MainStrategy,
|
|
12
|
-
interval: "5m",
|
|
13
|
-
getSignal: async (symbol) => {
|
|
14
|
-
|
|
15
|
-
const signalId = randomString();
|
|
16
|
-
|
|
17
|
-
const data_4h = await math_4h.getData(signalId, symbol);
|
|
18
|
-
|
|
19
|
-
if (data_4h.noTrades) {
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const data_15m = await math_15m.getData(signalId, symbol);
|
|
24
|
-
|
|
25
|
-
if (data_15m.position === 0) {
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (data_4h.allowShort && data_15m.position === 1) {
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (data_4h.allowLong && data_15m.position === -1) {
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
{
|
|
38
|
-
math_15m.dumpPlot(signalId, symbol);
|
|
39
|
-
math_4h.dumpPlot(signalId, symbol);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return await math_15m.getSignal(signalId, symbol);
|
|
43
|
-
},
|
|
44
|
-
riskList: [
|
|
45
|
-
RiskName.TakeProfitDistanceRisk,
|
|
46
|
-
RiskName.StopLossDistanceRisk
|
|
47
|
-
],
|
|
48
|
-
});
|
|
1
|
+
import { addStrategySchema } from "backtest-kit";
|
|
2
|
+
import { randomString } from "functools-kit";
|
|
3
|
+
|
|
4
|
+
import * as math_15m from "../../math/timeframe_15m.math.mjs";
|
|
5
|
+
import * as math_4h from "../../math/timeframe_4h.math.mjs";
|
|
6
|
+
|
|
7
|
+
import StrategyName from "../../enum/StrategyName.mjs";
|
|
8
|
+
import RiskName from "../../enum/RiskName.mjs";
|
|
9
|
+
|
|
10
|
+
addStrategySchema({
|
|
11
|
+
strategyName: StrategyName.MainStrategy,
|
|
12
|
+
interval: "5m",
|
|
13
|
+
getSignal: async (symbol) => {
|
|
14
|
+
|
|
15
|
+
const signalId = randomString();
|
|
16
|
+
|
|
17
|
+
const data_4h = await math_4h.getData(signalId, symbol);
|
|
18
|
+
|
|
19
|
+
if (data_4h.noTrades) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const data_15m = await math_15m.getData(signalId, symbol);
|
|
24
|
+
|
|
25
|
+
if (data_15m.position === 0) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (data_4h.allowShort && data_15m.position === 1) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (data_4h.allowLong && data_15m.position === -1) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
{
|
|
38
|
+
math_15m.dumpPlot(signalId, symbol);
|
|
39
|
+
math_4h.dumpPlot(signalId, symbol);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return await math_15m.getSignal(signalId, symbol);
|
|
43
|
+
},
|
|
44
|
+
riskList: [
|
|
45
|
+
RiskName.TakeProfitDistanceRisk,
|
|
46
|
+
RiskName.StopLossDistanceRisk
|
|
47
|
+
],
|
|
48
|
+
});
|
package/src/main/bootstrap.mjs
CHANGED
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
import { Backtest, listenError, overrideStrategySchema } from "backtest-kit";
|
|
2
|
-
|
|
3
|
-
import { getArgs } from "../utils/getArgs.mjs";
|
|
4
|
-
|
|
5
|
-
import ActionName from "../enum/ActionName.mjs";
|
|
6
|
-
|
|
7
|
-
const beginBacktest = async () => {
|
|
8
|
-
const { symbol, frameName, strategyName, exchangeName } = getArgs();
|
|
9
|
-
|
|
10
|
-
overrideStrategySchema({
|
|
11
|
-
strategyName,
|
|
12
|
-
actions: [
|
|
13
|
-
ActionName.BacktestPartialProfitTakingAction,
|
|
14
|
-
ActionName.BacktestLowerStopOnBreakevenAction,
|
|
15
|
-
ActionName.BacktestPositionMonitorAction,
|
|
16
|
-
],
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
Backtest.background(symbol, {
|
|
20
|
-
strategyName,
|
|
21
|
-
frameName,
|
|
22
|
-
exchangeName,
|
|
23
|
-
});
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const beginPaper = async () => {
|
|
27
|
-
throw new Error("Todo: implement");
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
const beginLive = async () => {
|
|
31
|
-
throw new Error("Todo: implement");
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const main = async () => {
|
|
35
|
-
const { backtest, live, paper } = getArgs();
|
|
36
|
-
|
|
37
|
-
if (backtest) {
|
|
38
|
-
await beginBacktest();
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (paper) {
|
|
42
|
-
await beginPaper();
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (live) {
|
|
46
|
-
await beginLive();
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
listenError(console.log);
|
|
51
|
-
|
|
52
|
-
main();
|
|
1
|
+
import { Backtest, listenError, overrideStrategySchema } from "backtest-kit";
|
|
2
|
+
|
|
3
|
+
import { getArgs } from "../utils/getArgs.mjs";
|
|
4
|
+
|
|
5
|
+
import ActionName from "../enum/ActionName.mjs";
|
|
6
|
+
|
|
7
|
+
const beginBacktest = async () => {
|
|
8
|
+
const { symbol, frameName, strategyName, exchangeName } = getArgs();
|
|
9
|
+
|
|
10
|
+
overrideStrategySchema({
|
|
11
|
+
strategyName,
|
|
12
|
+
actions: [
|
|
13
|
+
ActionName.BacktestPartialProfitTakingAction,
|
|
14
|
+
ActionName.BacktestLowerStopOnBreakevenAction,
|
|
15
|
+
ActionName.BacktestPositionMonitorAction,
|
|
16
|
+
],
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
Backtest.background(symbol, {
|
|
20
|
+
strategyName,
|
|
21
|
+
frameName,
|
|
22
|
+
exchangeName,
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const beginPaper = async () => {
|
|
27
|
+
throw new Error("Todo: implement");
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const beginLive = async () => {
|
|
31
|
+
throw new Error("Todo: implement");
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const main = async () => {
|
|
35
|
+
const { backtest, live, paper } = getArgs();
|
|
36
|
+
|
|
37
|
+
if (backtest) {
|
|
38
|
+
await beginBacktest();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (paper) {
|
|
42
|
+
await beginPaper();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (live) {
|
|
46
|
+
await beginLive();
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
listenError(console.log);
|
|
51
|
+
|
|
52
|
+
main();
|
|
@@ -1,68 +1,68 @@
|
|
|
1
|
-
import { Cache } from "backtest-kit";
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
run,
|
|
5
|
-
File,
|
|
6
|
-
toMarkdown,
|
|
7
|
-
toSignalDto,
|
|
8
|
-
extract,
|
|
9
|
-
dumpPlotData,
|
|
10
|
-
} from "@backtest-kit/pinets";
|
|
11
|
-
|
|
12
|
-
const SIGNAL_SCHEMA = {
|
|
13
|
-
position: "Signal",
|
|
14
|
-
priceOpen: "Close",
|
|
15
|
-
priceTakeProfit: "TakeProfit",
|
|
16
|
-
priceStopLoss: "StopLoss",
|
|
17
|
-
minuteEstimatedTime: "EstimatedTime",
|
|
18
|
-
d_RSI: "d_RSI",
|
|
19
|
-
d_EmaFast: "d_EmaFast",
|
|
20
|
-
d_EmaSlow: "d_EmaSlow",
|
|
21
|
-
d_EmaTrend: "d_EmaTrend",
|
|
22
|
-
d_ATR: "d_ATR",
|
|
23
|
-
d_Volume: "d_Volume",
|
|
24
|
-
d_VolMA: "d_VolMA",
|
|
25
|
-
d_VolSpike: "d_VolSpike",
|
|
26
|
-
d_Mom: "d_Mom",
|
|
27
|
-
d_MomUp: "d_MomUp",
|
|
28
|
-
d_MomDown: "d_MomDown",
|
|
29
|
-
d_TrendUp: "d_TrendUp",
|
|
30
|
-
d_TrendDown: "d_TrendDown",
|
|
31
|
-
d_LongCond: "d_LongCond",
|
|
32
|
-
d_ShortCond: "d_ShortCond",
|
|
33
|
-
d_BarsSinceSignal: "d_BarsSinceSignal",
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
export const getPlot = Cache.fn(
|
|
37
|
-
async (symbol) =>
|
|
38
|
-
await run(File.fromPath("timeframe_15m.pine"), {
|
|
39
|
-
symbol,
|
|
40
|
-
timeframe: "15m",
|
|
41
|
-
limit: 100,
|
|
42
|
-
}),
|
|
43
|
-
{
|
|
44
|
-
interval: "15m",
|
|
45
|
-
key: ([symbol]) => `${symbol}`,
|
|
46
|
-
},
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
export const getMarkdown = async (signalId, symbol) => {
|
|
50
|
-
const plots = await getPlot(symbol);
|
|
51
|
-
return await toMarkdown(signalId, plots, SIGNAL_SCHEMA);
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
export const getData = async (signalId, symbol) => {
|
|
55
|
-
const plots = await getPlot(symbol);
|
|
56
|
-
return await extract(plots, SIGNAL_SCHEMA);
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
export const getSignal = async (signalId, symbol) => {
|
|
60
|
-
const plots = await getPlot(symbol);
|
|
61
|
-
const result = await extract(plots, SIGNAL_SCHEMA);
|
|
62
|
-
return toSignalDto(signalId, result, null);
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
export const dumpPlot = async (signalId, symbol) => {
|
|
66
|
-
const plots = await getPlot(symbol);
|
|
67
|
-
dumpPlotData(signalId, plots, SIGNAL_SCHEMA, "math_15m");
|
|
68
|
-
};
|
|
1
|
+
import { Cache } from "backtest-kit";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
run,
|
|
5
|
+
File,
|
|
6
|
+
toMarkdown,
|
|
7
|
+
toSignalDto,
|
|
8
|
+
extract,
|
|
9
|
+
dumpPlotData,
|
|
10
|
+
} from "@backtest-kit/pinets";
|
|
11
|
+
|
|
12
|
+
const SIGNAL_SCHEMA = {
|
|
13
|
+
position: "Signal",
|
|
14
|
+
priceOpen: "Close",
|
|
15
|
+
priceTakeProfit: "TakeProfit",
|
|
16
|
+
priceStopLoss: "StopLoss",
|
|
17
|
+
minuteEstimatedTime: "EstimatedTime",
|
|
18
|
+
d_RSI: "d_RSI",
|
|
19
|
+
d_EmaFast: "d_EmaFast",
|
|
20
|
+
d_EmaSlow: "d_EmaSlow",
|
|
21
|
+
d_EmaTrend: "d_EmaTrend",
|
|
22
|
+
d_ATR: "d_ATR",
|
|
23
|
+
d_Volume: "d_Volume",
|
|
24
|
+
d_VolMA: "d_VolMA",
|
|
25
|
+
d_VolSpike: "d_VolSpike",
|
|
26
|
+
d_Mom: "d_Mom",
|
|
27
|
+
d_MomUp: "d_MomUp",
|
|
28
|
+
d_MomDown: "d_MomDown",
|
|
29
|
+
d_TrendUp: "d_TrendUp",
|
|
30
|
+
d_TrendDown: "d_TrendDown",
|
|
31
|
+
d_LongCond: "d_LongCond",
|
|
32
|
+
d_ShortCond: "d_ShortCond",
|
|
33
|
+
d_BarsSinceSignal: "d_BarsSinceSignal",
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const getPlot = Cache.fn(
|
|
37
|
+
async (symbol) =>
|
|
38
|
+
await run(File.fromPath("timeframe_15m.pine"), {
|
|
39
|
+
symbol,
|
|
40
|
+
timeframe: "15m",
|
|
41
|
+
limit: 100,
|
|
42
|
+
}),
|
|
43
|
+
{
|
|
44
|
+
interval: "15m",
|
|
45
|
+
key: ([symbol]) => `${symbol}`,
|
|
46
|
+
},
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
export const getMarkdown = async (signalId, symbol) => {
|
|
50
|
+
const plots = await getPlot(symbol);
|
|
51
|
+
return await toMarkdown(signalId, plots, SIGNAL_SCHEMA);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const getData = async (signalId, symbol) => {
|
|
55
|
+
const plots = await getPlot(symbol);
|
|
56
|
+
return await extract(plots, SIGNAL_SCHEMA);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const getSignal = async (signalId, symbol) => {
|
|
60
|
+
const plots = await getPlot(symbol);
|
|
61
|
+
const result = await extract(plots, SIGNAL_SCHEMA);
|
|
62
|
+
return toSignalDto(signalId, result, null);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export const dumpPlot = async (signalId, symbol) => {
|
|
66
|
+
const plots = await getPlot(symbol);
|
|
67
|
+
dumpPlotData(signalId, plots, SIGNAL_SCHEMA, "math_15m");
|
|
68
|
+
};
|
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
import { Cache } from "backtest-kit";
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
run,
|
|
5
|
-
File,
|
|
6
|
-
toMarkdown,
|
|
7
|
-
toSignalDto,
|
|
8
|
-
extract,
|
|
9
|
-
dumpPlotData,
|
|
10
|
-
} from "@backtest-kit/pinets";
|
|
11
|
-
|
|
12
|
-
const SIGNAL_SCHEMA = {
|
|
13
|
-
allowLong: "AllowLong",
|
|
14
|
-
allowShort: "AllowShort",
|
|
15
|
-
allowBoth: "AllowBoth",
|
|
16
|
-
noTrades: "NoTrades",
|
|
17
|
-
rsi: "RSI",
|
|
18
|
-
adx: "ADX",
|
|
19
|
-
d_MACDLine: "d_MACDLine",
|
|
20
|
-
d_SignalLine: "d_SignalLine",
|
|
21
|
-
d_MACDHist: "d_MACDHist",
|
|
22
|
-
d_DIPlus: "d_DIPlus",
|
|
23
|
-
d_DIMinus: "d_DIMinus",
|
|
24
|
-
d_StrongTrend: "d_StrongTrend",
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export const getPlot = Cache.fn(
|
|
28
|
-
async (symbol) =>
|
|
29
|
-
await run(File.fromPath("timeframe_4h.pine"), {
|
|
30
|
-
symbol,
|
|
31
|
-
timeframe: "4h",
|
|
32
|
-
limit: 100,
|
|
33
|
-
}),
|
|
34
|
-
{
|
|
35
|
-
interval: "4h",
|
|
36
|
-
key: ([symbol]) => `${symbol}`,
|
|
37
|
-
},
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
export const getMarkdown = async (signalId, symbol) => {
|
|
41
|
-
const plots = await getPlot(symbol);
|
|
42
|
-
return await toMarkdown(signalId, plots, SIGNAL_SCHEMA);
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export const getData = async (signalId, symbol) => {
|
|
46
|
-
const plots = await getPlot(symbol);
|
|
47
|
-
return await extract(plots, SIGNAL_SCHEMA);
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
export const dumpPlot = async (signalId, symbol) => {
|
|
51
|
-
const plots = await getPlot(symbol);
|
|
52
|
-
dumpPlotData(signalId, plots, SIGNAL_SCHEMA, "math_4h");
|
|
53
|
-
};
|
|
1
|
+
import { Cache } from "backtest-kit";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
run,
|
|
5
|
+
File,
|
|
6
|
+
toMarkdown,
|
|
7
|
+
toSignalDto,
|
|
8
|
+
extract,
|
|
9
|
+
dumpPlotData,
|
|
10
|
+
} from "@backtest-kit/pinets";
|
|
11
|
+
|
|
12
|
+
const SIGNAL_SCHEMA = {
|
|
13
|
+
allowLong: "AllowLong",
|
|
14
|
+
allowShort: "AllowShort",
|
|
15
|
+
allowBoth: "AllowBoth",
|
|
16
|
+
noTrades: "NoTrades",
|
|
17
|
+
rsi: "RSI",
|
|
18
|
+
adx: "ADX",
|
|
19
|
+
d_MACDLine: "d_MACDLine",
|
|
20
|
+
d_SignalLine: "d_SignalLine",
|
|
21
|
+
d_MACDHist: "d_MACDHist",
|
|
22
|
+
d_DIPlus: "d_DIPlus",
|
|
23
|
+
d_DIMinus: "d_DIMinus",
|
|
24
|
+
d_StrongTrend: "d_StrongTrend",
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const getPlot = Cache.fn(
|
|
28
|
+
async (symbol) =>
|
|
29
|
+
await run(File.fromPath("timeframe_4h.pine"), {
|
|
30
|
+
symbol,
|
|
31
|
+
timeframe: "4h",
|
|
32
|
+
limit: 100,
|
|
33
|
+
}),
|
|
34
|
+
{
|
|
35
|
+
interval: "4h",
|
|
36
|
+
key: ([symbol]) => `${symbol}`,
|
|
37
|
+
},
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
export const getMarkdown = async (signalId, symbol) => {
|
|
41
|
+
const plots = await getPlot(symbol);
|
|
42
|
+
return await toMarkdown(signalId, plots, SIGNAL_SCHEMA);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const getData = async (signalId, symbol) => {
|
|
46
|
+
const plots = await getPlot(symbol);
|
|
47
|
+
return await extract(plots, SIGNAL_SCHEMA);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const dumpPlot = async (signalId, symbol) => {
|
|
51
|
+
const plots = await getPlot(symbol);
|
|
52
|
+
dumpPlotData(signalId, plots, SIGNAL_SCHEMA, "math_4h");
|
|
53
|
+
};
|
package/src/utils/getArgs.mjs
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { singleshot } from "functools-kit";
|
|
2
|
-
import { parseArgs } from "backtest-kit";
|
|
3
|
-
|
|
4
|
-
import ExchangeName from "../enum/ExchangeName.mjs";
|
|
5
|
-
import StrategyName from "../enum/StrategyName.mjs";
|
|
6
|
-
import FrameName from "../enum/FrameName.mjs";
|
|
7
|
-
|
|
8
|
-
const DEFAULT_SYMBOL = "BTCUSDT";
|
|
9
|
-
|
|
10
|
-
export const getArgs = singleshot(() =>
|
|
11
|
-
parseArgs({
|
|
12
|
-
exchangeName: ExchangeName.BinanceExchange,
|
|
13
|
-
strategyName: StrategyName.MainStrategy,
|
|
14
|
-
frameName: FrameName.October2025,
|
|
15
|
-
symbol: DEFAULT_SYMBOL,
|
|
16
|
-
})
|
|
17
|
-
);
|
|
1
|
+
import { singleshot } from "functools-kit";
|
|
2
|
+
import { parseArgs } from "backtest-kit";
|
|
3
|
+
|
|
4
|
+
import ExchangeName from "../enum/ExchangeName.mjs";
|
|
5
|
+
import StrategyName from "../enum/StrategyName.mjs";
|
|
6
|
+
import FrameName from "../enum/FrameName.mjs";
|
|
7
|
+
|
|
8
|
+
const DEFAULT_SYMBOL = "BTCUSDT";
|
|
9
|
+
|
|
10
|
+
export const getArgs = singleshot(() =>
|
|
11
|
+
parseArgs({
|
|
12
|
+
exchangeName: ExchangeName.BinanceExchange,
|
|
13
|
+
strategyName: StrategyName.MainStrategy,
|
|
14
|
+
frameName: FrameName.October2025,
|
|
15
|
+
symbol: DEFAULT_SYMBOL,
|
|
16
|
+
})
|
|
17
|
+
);
|