@backtest-kit/sidekick 9.5.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,34 +1,34 @@
|
|
|
1
|
-
version: "3.8"
|
|
2
|
-
|
|
3
|
-
services:
|
|
4
|
-
ollama:
|
|
5
|
-
build: .
|
|
6
|
-
container_name: ollama
|
|
7
|
-
ports:
|
|
8
|
-
- "11434:11434"
|
|
9
|
-
volumes:
|
|
10
|
-
- ./.ollama:/root/.ollama
|
|
11
|
-
environment:
|
|
12
|
-
OLLAMA_HOST: 0.0.0.0
|
|
13
|
-
OLLAMA_MAX_LOADED_MODELS: 2
|
|
14
|
-
OLLAMA_NUM_PARALLEL: 8
|
|
15
|
-
OLLAMA_MAX_QUEUE: 96
|
|
16
|
-
OLLAMA_KEEP_ALIVE: 24h
|
|
17
|
-
OLLAMA_FLASH_ATTENTION: 1
|
|
18
|
-
OLLAMA_KV_CACHE_TYPE: q4_0
|
|
19
|
-
NVIDIA_VISIBLE_DEVICES: all
|
|
20
|
-
NVIDIA_DRIVER_CAPABILITIES: compute,utility
|
|
21
|
-
deploy:
|
|
22
|
-
resources:
|
|
23
|
-
reservations:
|
|
24
|
-
devices:
|
|
25
|
-
- driver: nvidia
|
|
26
|
-
count: all
|
|
27
|
-
capabilities: [gpu]
|
|
28
|
-
restart: always
|
|
29
|
-
healthcheck:
|
|
30
|
-
test: ["CMD", "curl", "-f", "http://localhost:11434/api/version"]
|
|
31
|
-
interval: 30s
|
|
32
|
-
timeout: 5s
|
|
33
|
-
retries: 3
|
|
34
|
-
start_period: 20s
|
|
1
|
+
version: "3.8"
|
|
2
|
+
|
|
3
|
+
services:
|
|
4
|
+
ollama:
|
|
5
|
+
build: .
|
|
6
|
+
container_name: ollama
|
|
7
|
+
ports:
|
|
8
|
+
- "11434:11434"
|
|
9
|
+
volumes:
|
|
10
|
+
- ./.ollama:/root/.ollama
|
|
11
|
+
environment:
|
|
12
|
+
OLLAMA_HOST: 0.0.0.0
|
|
13
|
+
OLLAMA_MAX_LOADED_MODELS: 2
|
|
14
|
+
OLLAMA_NUM_PARALLEL: 8
|
|
15
|
+
OLLAMA_MAX_QUEUE: 96
|
|
16
|
+
OLLAMA_KEEP_ALIVE: 24h
|
|
17
|
+
OLLAMA_FLASH_ATTENTION: 1
|
|
18
|
+
OLLAMA_KV_CACHE_TYPE: q4_0
|
|
19
|
+
NVIDIA_VISIBLE_DEVICES: all
|
|
20
|
+
NVIDIA_DRIVER_CAPABILITIES: compute,utility
|
|
21
|
+
deploy:
|
|
22
|
+
resources:
|
|
23
|
+
reservations:
|
|
24
|
+
devices:
|
|
25
|
+
- driver: nvidia
|
|
26
|
+
count: all
|
|
27
|
+
capabilities: [gpu]
|
|
28
|
+
restart: always
|
|
29
|
+
healthcheck:
|
|
30
|
+
test: ["CMD", "curl", "-f", "http://localhost:11434/api/version"]
|
|
31
|
+
interval: 30s
|
|
32
|
+
timeout: 5s
|
|
33
|
+
retries: 3
|
|
34
|
+
start_period: 20s
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
watch -n 1 -d nvidia-smi
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
watch -n 1 -d nvidia-smi
|
|
@@ -1,47 +1,47 @@
|
|
|
1
|
-
import { addExchangeSchema, warmCandles } from "backtest-kit";
|
|
2
|
-
import { singleshot } from "functools-kit";
|
|
3
|
-
import ccxt from "ccxt";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const getExchange = singleshot(async () => {
|
|
7
|
-
const exchange = new ccxt.binance({
|
|
8
|
-
options: {
|
|
9
|
-
defaultType: "spot",
|
|
10
|
-
adjustForTimeDifference: true,
|
|
11
|
-
recvWindow: 60000,
|
|
12
|
-
},
|
|
13
|
-
enableRateLimit: true,
|
|
14
|
-
});
|
|
15
|
-
await exchange.loadMarkets();
|
|
16
|
-
return exchange;
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
addExchangeSchema({
|
|
20
|
-
exchangeName: "binance_exchange",
|
|
21
|
-
getCandles: async (symbol, interval, since, limit) => {
|
|
22
|
-
const exchange = await getExchange();
|
|
23
|
-
const candles = await exchange.fetchOHLCV(
|
|
24
|
-
symbol,
|
|
25
|
-
interval,
|
|
26
|
-
since.getTime(),
|
|
27
|
-
limit,
|
|
28
|
-
);
|
|
29
|
-
return candles.map(([timestamp, open, high, low, close, volume]) => ({
|
|
30
|
-
timestamp,
|
|
31
|
-
open,
|
|
32
|
-
high,
|
|
33
|
-
low,
|
|
34
|
-
close,
|
|
35
|
-
volume,
|
|
36
|
-
}));
|
|
37
|
-
},
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
const from = new Date("2024-02-01T00:00:00Z");
|
|
41
|
-
const to = new Date("2024-02-29T23:59:59Z");
|
|
42
|
-
const symbol = "BTCUSDT";
|
|
43
|
-
const exchangeName = "binance_exchange";
|
|
44
|
-
|
|
45
|
-
await warmCandles({ exchangeName, from, to, interval: "1m", symbol });
|
|
46
|
-
await warmCandles({ exchangeName, from, to, interval: "15m", symbol });
|
|
47
|
-
await warmCandles({ exchangeName, from, to, interval: "4h", symbol });
|
|
1
|
+
import { addExchangeSchema, warmCandles } from "backtest-kit";
|
|
2
|
+
import { singleshot } from "functools-kit";
|
|
3
|
+
import ccxt from "ccxt";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
const getExchange = singleshot(async () => {
|
|
7
|
+
const exchange = new ccxt.binance({
|
|
8
|
+
options: {
|
|
9
|
+
defaultType: "spot",
|
|
10
|
+
adjustForTimeDifference: true,
|
|
11
|
+
recvWindow: 60000,
|
|
12
|
+
},
|
|
13
|
+
enableRateLimit: true,
|
|
14
|
+
});
|
|
15
|
+
await exchange.loadMarkets();
|
|
16
|
+
return exchange;
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
addExchangeSchema({
|
|
20
|
+
exchangeName: "binance_exchange",
|
|
21
|
+
getCandles: async (symbol, interval, since, limit) => {
|
|
22
|
+
const exchange = await getExchange();
|
|
23
|
+
const candles = await exchange.fetchOHLCV(
|
|
24
|
+
symbol,
|
|
25
|
+
interval,
|
|
26
|
+
since.getTime(),
|
|
27
|
+
limit,
|
|
28
|
+
);
|
|
29
|
+
return candles.map(([timestamp, open, high, low, close, volume]) => ({
|
|
30
|
+
timestamp,
|
|
31
|
+
open,
|
|
32
|
+
high,
|
|
33
|
+
low,
|
|
34
|
+
close,
|
|
35
|
+
volume,
|
|
36
|
+
}));
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const from = new Date("2024-02-01T00:00:00Z");
|
|
41
|
+
const to = new Date("2024-02-29T23:59:59Z");
|
|
42
|
+
const symbol = "BTCUSDT";
|
|
43
|
+
const exchangeName = "binance_exchange";
|
|
44
|
+
|
|
45
|
+
await warmCandles({ exchangeName, from, to, interval: "1m", symbol });
|
|
46
|
+
await warmCandles({ exchangeName, from, to, interval: "15m", symbol });
|
|
47
|
+
await warmCandles({ exchangeName, from, to, interval: "4h", symbol });
|
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
import { Ollama } from "ollama";
|
|
2
|
-
|
|
3
|
-
const MODEL_NAME = "glm-4.7-flash:q4_K_M";
|
|
4
|
-
|
|
5
|
-
const ollama = new Ollama({ host: "http://127.0.0.1:11434" });
|
|
6
|
-
|
|
7
|
-
console.log(`Loading model ${MODEL_NAME}`);
|
|
8
|
-
|
|
9
|
-
const pull = async () => {
|
|
10
|
-
const response = await ollama.pull({
|
|
11
|
-
model: MODEL_NAME,
|
|
12
|
-
stream: true,
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
for await (const part of response) {
|
|
16
|
-
if (!part.completed || !part.total) {
|
|
17
|
-
continue;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// Calculate progress percentage
|
|
21
|
-
const progress =
|
|
22
|
-
part.total > 0 ? ((part.completed / part.total) * 100).toFixed(1) : 0;
|
|
23
|
-
|
|
24
|
-
// Create simple progress bar
|
|
25
|
-
const barLength = 40;
|
|
26
|
-
const filledLength = Math.round((barLength * part.completed) / part.total);
|
|
27
|
-
const bar = "█".repeat(filledLength) + "░".repeat(barLength - filledLength);
|
|
28
|
-
|
|
29
|
-
// Display progress
|
|
30
|
-
process.stdout.write(`\r[${bar}] ${progress}% ${part.status}`);
|
|
31
|
-
|
|
32
|
-
if (part.status === "success") {
|
|
33
|
-
console.log("\nModel pulled successfully!");
|
|
34
|
-
break;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
console.log("Done!");
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
await pull();
|
|
42
|
-
|
|
1
|
+
import { Ollama } from "ollama";
|
|
2
|
+
|
|
3
|
+
const MODEL_NAME = "glm-4.7-flash:q4_K_M";
|
|
4
|
+
|
|
5
|
+
const ollama = new Ollama({ host: "http://127.0.0.1:11434" });
|
|
6
|
+
|
|
7
|
+
console.log(`Loading model ${MODEL_NAME}`);
|
|
8
|
+
|
|
9
|
+
const pull = async () => {
|
|
10
|
+
const response = await ollama.pull({
|
|
11
|
+
model: MODEL_NAME,
|
|
12
|
+
stream: true,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
for await (const part of response) {
|
|
16
|
+
if (!part.completed || !part.total) {
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Calculate progress percentage
|
|
21
|
+
const progress =
|
|
22
|
+
part.total > 0 ? ((part.completed / part.total) * 100).toFixed(1) : 0;
|
|
23
|
+
|
|
24
|
+
// Create simple progress bar
|
|
25
|
+
const barLength = 40;
|
|
26
|
+
const filledLength = Math.round((barLength * part.completed) / part.total);
|
|
27
|
+
const bar = "█".repeat(filledLength) + "░".repeat(barLength - filledLength);
|
|
28
|
+
|
|
29
|
+
// Display progress
|
|
30
|
+
process.stdout.write(`\r[${bar}] ${progress}% ${part.status}`);
|
|
31
|
+
|
|
32
|
+
if (part.status === "success") {
|
|
33
|
+
console.log("\nModel pulled successfully!");
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
console.log("Done!");
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
await pull();
|
|
42
|
+
|
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
import { addExchangeSchema, checkCandles } from "backtest-kit";
|
|
2
|
-
import { singleshot } from "functools-kit";
|
|
3
|
-
import ccxt from "ccxt";
|
|
4
|
-
|
|
5
|
-
const getExchange = singleshot(async () => {
|
|
6
|
-
const exchange = new ccxt.binance({
|
|
7
|
-
options: {
|
|
8
|
-
defaultType: "spot",
|
|
9
|
-
adjustForTimeDifference: true,
|
|
10
|
-
recvWindow: 60000,
|
|
11
|
-
},
|
|
12
|
-
enableRateLimit: true,
|
|
13
|
-
});
|
|
14
|
-
await exchange.loadMarkets();
|
|
15
|
-
return exchange;
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
addExchangeSchema({
|
|
19
|
-
exchangeName: "binance_exchange",
|
|
20
|
-
getCandles: async (symbol, interval, since, limit) => {
|
|
21
|
-
const exchange = await getExchange();
|
|
22
|
-
const candles = await exchange.fetchOHLCV(
|
|
23
|
-
symbol,
|
|
24
|
-
interval,
|
|
25
|
-
since.getTime(),
|
|
26
|
-
limit,
|
|
27
|
-
);
|
|
28
|
-
return candles.map(([timestamp, open, high, low, close, volume]) => ({
|
|
29
|
-
timestamp,
|
|
30
|
-
open,
|
|
31
|
-
high,
|
|
32
|
-
low,
|
|
33
|
-
close,
|
|
34
|
-
volume,
|
|
35
|
-
}));
|
|
36
|
-
},
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
const from = new Date("2024-02-01T00:00:00Z");
|
|
40
|
-
const to = new Date("2024-02-29T23:59:59Z");
|
|
41
|
-
const symbol = "BTCUSDT";
|
|
42
|
-
const exchangeName = "binance_exchange";
|
|
43
|
-
|
|
44
|
-
await checkCandles({ exchangeName, from, to, interval: "1m", symbol });
|
|
45
|
-
await checkCandles({ exchangeName, from, to, interval: "15m", symbol });
|
|
46
|
-
await checkCandles({ exchangeName, from, to, interval: "4h", symbol });
|
|
1
|
+
import { addExchangeSchema, checkCandles } from "backtest-kit";
|
|
2
|
+
import { singleshot } from "functools-kit";
|
|
3
|
+
import ccxt from "ccxt";
|
|
4
|
+
|
|
5
|
+
const getExchange = singleshot(async () => {
|
|
6
|
+
const exchange = new ccxt.binance({
|
|
7
|
+
options: {
|
|
8
|
+
defaultType: "spot",
|
|
9
|
+
adjustForTimeDifference: true,
|
|
10
|
+
recvWindow: 60000,
|
|
11
|
+
},
|
|
12
|
+
enableRateLimit: true,
|
|
13
|
+
});
|
|
14
|
+
await exchange.loadMarkets();
|
|
15
|
+
return exchange;
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
addExchangeSchema({
|
|
19
|
+
exchangeName: "binance_exchange",
|
|
20
|
+
getCandles: async (symbol, interval, since, limit) => {
|
|
21
|
+
const exchange = await getExchange();
|
|
22
|
+
const candles = await exchange.fetchOHLCV(
|
|
23
|
+
symbol,
|
|
24
|
+
interval,
|
|
25
|
+
since.getTime(),
|
|
26
|
+
limit,
|
|
27
|
+
);
|
|
28
|
+
return candles.map(([timestamp, open, high, low, close, volume]) => ({
|
|
29
|
+
timestamp,
|
|
30
|
+
open,
|
|
31
|
+
high,
|
|
32
|
+
low,
|
|
33
|
+
close,
|
|
34
|
+
volume,
|
|
35
|
+
}));
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const from = new Date("2024-02-01T00:00:00Z");
|
|
40
|
+
const to = new Date("2024-02-29T23:59:59Z");
|
|
41
|
+
const symbol = "BTCUSDT";
|
|
42
|
+
const exchangeName = "binance_exchange";
|
|
43
|
+
|
|
44
|
+
await checkCandles({ exchangeName, from, to, interval: "1m", symbol });
|
|
45
|
+
await checkCandles({ exchangeName, from, to, interval: "15m", symbol });
|
|
46
|
+
await checkCandles({ exchangeName, from, to, interval: "4h", symbol });
|
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
import { addExchangeSchema } from "backtest-kit";
|
|
2
|
-
import { singleshot, randomString } from "functools-kit";
|
|
3
|
-
import { run, File, toMarkdown } from "@backtest-kit/pinets";
|
|
4
|
-
import ccxt from "ccxt";
|
|
5
|
-
|
|
6
|
-
const SIGNAL_SCHEMA = {
|
|
7
|
-
position: "Signal",
|
|
8
|
-
priceOpen: "Close",
|
|
9
|
-
priceTakeProfit: "TakeProfit",
|
|
10
|
-
priceStopLoss: "StopLoss",
|
|
11
|
-
minuteEstimatedTime: "EstimatedTime",
|
|
12
|
-
d_RSI: "d_RSI",
|
|
13
|
-
d_EmaFast: "d_EmaFast",
|
|
14
|
-
d_EmaSlow: "d_EmaSlow",
|
|
15
|
-
d_EmaTrend: "d_EmaTrend",
|
|
16
|
-
d_ATR: "d_ATR",
|
|
17
|
-
d_Volume: "d_Volume",
|
|
18
|
-
d_VolMA: "d_VolMA",
|
|
19
|
-
d_VolSpike: "d_VolSpike",
|
|
20
|
-
d_Mom: "d_Mom",
|
|
21
|
-
d_MomUp: "d_MomUp",
|
|
22
|
-
d_MomDown: "d_MomDown",
|
|
23
|
-
d_TrendUp: "d_TrendUp",
|
|
24
|
-
d_TrendDown: "d_TrendDown",
|
|
25
|
-
d_LongCond: "d_LongCond",
|
|
26
|
-
d_ShortCond: "d_ShortCond",
|
|
27
|
-
d_BarsSinceSignal: "d_BarsSinceSignal",
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
const SIGNAL_ID = randomString();
|
|
31
|
-
|
|
32
|
-
const getExchange = singleshot(async () => {
|
|
33
|
-
const exchange = new ccxt.binance({
|
|
34
|
-
options: {
|
|
35
|
-
defaultType: "spot",
|
|
36
|
-
adjustForTimeDifference: true,
|
|
37
|
-
recvWindow: 60000,
|
|
38
|
-
},
|
|
39
|
-
enableRateLimit: true,
|
|
40
|
-
});
|
|
41
|
-
await exchange.loadMarkets();
|
|
42
|
-
return exchange;
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
addExchangeSchema({
|
|
46
|
-
exchangeName: "binance_exchange",
|
|
47
|
-
getCandles: async (symbol, interval, since, limit) => {
|
|
48
|
-
const exchange = await getExchange();
|
|
49
|
-
const candles = await exchange.fetchOHLCV(
|
|
50
|
-
symbol,
|
|
51
|
-
interval,
|
|
52
|
-
since.getTime(),
|
|
53
|
-
limit,
|
|
54
|
-
);
|
|
55
|
-
return candles.map(([timestamp, open, high, low, close, volume]) => ({
|
|
56
|
-
timestamp,
|
|
57
|
-
open,
|
|
58
|
-
high,
|
|
59
|
-
low,
|
|
60
|
-
close,
|
|
61
|
-
volume,
|
|
62
|
-
}));
|
|
63
|
-
},
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
const plots = await run(
|
|
67
|
-
File.fromPath("timeframe_15m.pine"),
|
|
68
|
-
{
|
|
69
|
-
symbol: "BTCUSDT",
|
|
70
|
-
timeframe: "15m",
|
|
71
|
-
limit: 60,
|
|
72
|
-
},
|
|
73
|
-
"binance_exchange",
|
|
74
|
-
new Date("2025-09-23T16:00:00.000Z"),
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
console.log(await toMarkdown(SIGNAL_ID, plots, SIGNAL_SCHEMA));
|
|
1
|
+
import { addExchangeSchema } from "backtest-kit";
|
|
2
|
+
import { singleshot, randomString } from "functools-kit";
|
|
3
|
+
import { run, File, toMarkdown } from "@backtest-kit/pinets";
|
|
4
|
+
import ccxt from "ccxt";
|
|
5
|
+
|
|
6
|
+
const SIGNAL_SCHEMA = {
|
|
7
|
+
position: "Signal",
|
|
8
|
+
priceOpen: "Close",
|
|
9
|
+
priceTakeProfit: "TakeProfit",
|
|
10
|
+
priceStopLoss: "StopLoss",
|
|
11
|
+
minuteEstimatedTime: "EstimatedTime",
|
|
12
|
+
d_RSI: "d_RSI",
|
|
13
|
+
d_EmaFast: "d_EmaFast",
|
|
14
|
+
d_EmaSlow: "d_EmaSlow",
|
|
15
|
+
d_EmaTrend: "d_EmaTrend",
|
|
16
|
+
d_ATR: "d_ATR",
|
|
17
|
+
d_Volume: "d_Volume",
|
|
18
|
+
d_VolMA: "d_VolMA",
|
|
19
|
+
d_VolSpike: "d_VolSpike",
|
|
20
|
+
d_Mom: "d_Mom",
|
|
21
|
+
d_MomUp: "d_MomUp",
|
|
22
|
+
d_MomDown: "d_MomDown",
|
|
23
|
+
d_TrendUp: "d_TrendUp",
|
|
24
|
+
d_TrendDown: "d_TrendDown",
|
|
25
|
+
d_LongCond: "d_LongCond",
|
|
26
|
+
d_ShortCond: "d_ShortCond",
|
|
27
|
+
d_BarsSinceSignal: "d_BarsSinceSignal",
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const SIGNAL_ID = randomString();
|
|
31
|
+
|
|
32
|
+
const getExchange = singleshot(async () => {
|
|
33
|
+
const exchange = new ccxt.binance({
|
|
34
|
+
options: {
|
|
35
|
+
defaultType: "spot",
|
|
36
|
+
adjustForTimeDifference: true,
|
|
37
|
+
recvWindow: 60000,
|
|
38
|
+
},
|
|
39
|
+
enableRateLimit: true,
|
|
40
|
+
});
|
|
41
|
+
await exchange.loadMarkets();
|
|
42
|
+
return exchange;
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
addExchangeSchema({
|
|
46
|
+
exchangeName: "binance_exchange",
|
|
47
|
+
getCandles: async (symbol, interval, since, limit) => {
|
|
48
|
+
const exchange = await getExchange();
|
|
49
|
+
const candles = await exchange.fetchOHLCV(
|
|
50
|
+
symbol,
|
|
51
|
+
interval,
|
|
52
|
+
since.getTime(),
|
|
53
|
+
limit,
|
|
54
|
+
);
|
|
55
|
+
return candles.map(([timestamp, open, high, low, close, volume]) => ({
|
|
56
|
+
timestamp,
|
|
57
|
+
open,
|
|
58
|
+
high,
|
|
59
|
+
low,
|
|
60
|
+
close,
|
|
61
|
+
volume,
|
|
62
|
+
}));
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const plots = await run(
|
|
67
|
+
File.fromPath("timeframe_15m.pine"),
|
|
68
|
+
{
|
|
69
|
+
symbol: "BTCUSDT",
|
|
70
|
+
timeframe: "15m",
|
|
71
|
+
limit: 60,
|
|
72
|
+
},
|
|
73
|
+
"binance_exchange",
|
|
74
|
+
new Date("2025-09-23T16:00:00.000Z"),
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
console.log(await toMarkdown(SIGNAL_ID, plots, SIGNAL_SCHEMA));
|
|
@@ -1,68 +1,68 @@
|
|
|
1
|
-
import { addExchangeSchema } from "backtest-kit";
|
|
2
|
-
import { singleshot, randomString } from "functools-kit";
|
|
3
|
-
import { run, File, toMarkdown } from "@backtest-kit/pinets";
|
|
4
|
-
import ccxt from "ccxt";
|
|
5
|
-
|
|
6
|
-
const SIGNAL_SCHEMA = {
|
|
7
|
-
allowLong: "AllowLong",
|
|
8
|
-
allowShort: "AllowShort",
|
|
9
|
-
allowBoth: "AllowBoth",
|
|
10
|
-
noTrades: "NoTrades",
|
|
11
|
-
rsi: "RSI",
|
|
12
|
-
adx: "ADX",
|
|
13
|
-
d_MACDLine: "d_MACDLine",
|
|
14
|
-
d_SignalLine: "d_SignalLine",
|
|
15
|
-
d_MACDHist: "d_MACDHist",
|
|
16
|
-
d_DIPlus: "d_DIPlus",
|
|
17
|
-
d_DIMinus: "d_DIMinus",
|
|
18
|
-
d_StrongTrend: "d_StrongTrend",
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const SIGNAL_ID = randomString();
|
|
22
|
-
|
|
23
|
-
const getExchange = singleshot(async () => {
|
|
24
|
-
const exchange = new ccxt.binance({
|
|
25
|
-
options: {
|
|
26
|
-
defaultType: "spot",
|
|
27
|
-
adjustForTimeDifference: true,
|
|
28
|
-
recvWindow: 60000,
|
|
29
|
-
},
|
|
30
|
-
enableRateLimit: true,
|
|
31
|
-
});
|
|
32
|
-
await exchange.loadMarkets();
|
|
33
|
-
return exchange;
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
addExchangeSchema({
|
|
37
|
-
exchangeName: "binance_exchange",
|
|
38
|
-
getCandles: async (symbol, interval, since, limit) => {
|
|
39
|
-
const exchange = await getExchange();
|
|
40
|
-
const candles = await exchange.fetchOHLCV(
|
|
41
|
-
symbol,
|
|
42
|
-
interval,
|
|
43
|
-
since.getTime(),
|
|
44
|
-
limit,
|
|
45
|
-
);
|
|
46
|
-
return candles.map(([timestamp, open, high, low, close, volume]) => ({
|
|
47
|
-
timestamp,
|
|
48
|
-
open,
|
|
49
|
-
high,
|
|
50
|
-
low,
|
|
51
|
-
close,
|
|
52
|
-
volume,
|
|
53
|
-
}));
|
|
54
|
-
},
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
const plots = await run(
|
|
58
|
-
File.fromPath("timeframe_4h.pine"),
|
|
59
|
-
{
|
|
60
|
-
symbol: "BTCUSDT",
|
|
61
|
-
timeframe: "4h",
|
|
62
|
-
limit: 60,
|
|
63
|
-
},
|
|
64
|
-
"binance_exchange",
|
|
65
|
-
new Date("2025-09-23T23:00:00.000Z"),
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
console.log(await toMarkdown(SIGNAL_ID, plots, SIGNAL_SCHEMA));
|
|
1
|
+
import { addExchangeSchema } from "backtest-kit";
|
|
2
|
+
import { singleshot, randomString } from "functools-kit";
|
|
3
|
+
import { run, File, toMarkdown } from "@backtest-kit/pinets";
|
|
4
|
+
import ccxt from "ccxt";
|
|
5
|
+
|
|
6
|
+
const SIGNAL_SCHEMA = {
|
|
7
|
+
allowLong: "AllowLong",
|
|
8
|
+
allowShort: "AllowShort",
|
|
9
|
+
allowBoth: "AllowBoth",
|
|
10
|
+
noTrades: "NoTrades",
|
|
11
|
+
rsi: "RSI",
|
|
12
|
+
adx: "ADX",
|
|
13
|
+
d_MACDLine: "d_MACDLine",
|
|
14
|
+
d_SignalLine: "d_SignalLine",
|
|
15
|
+
d_MACDHist: "d_MACDHist",
|
|
16
|
+
d_DIPlus: "d_DIPlus",
|
|
17
|
+
d_DIMinus: "d_DIMinus",
|
|
18
|
+
d_StrongTrend: "d_StrongTrend",
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const SIGNAL_ID = randomString();
|
|
22
|
+
|
|
23
|
+
const getExchange = singleshot(async () => {
|
|
24
|
+
const exchange = new ccxt.binance({
|
|
25
|
+
options: {
|
|
26
|
+
defaultType: "spot",
|
|
27
|
+
adjustForTimeDifference: true,
|
|
28
|
+
recvWindow: 60000,
|
|
29
|
+
},
|
|
30
|
+
enableRateLimit: true,
|
|
31
|
+
});
|
|
32
|
+
await exchange.loadMarkets();
|
|
33
|
+
return exchange;
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
addExchangeSchema({
|
|
37
|
+
exchangeName: "binance_exchange",
|
|
38
|
+
getCandles: async (symbol, interval, since, limit) => {
|
|
39
|
+
const exchange = await getExchange();
|
|
40
|
+
const candles = await exchange.fetchOHLCV(
|
|
41
|
+
symbol,
|
|
42
|
+
interval,
|
|
43
|
+
since.getTime(),
|
|
44
|
+
limit,
|
|
45
|
+
);
|
|
46
|
+
return candles.map(([timestamp, open, high, low, close, volume]) => ({
|
|
47
|
+
timestamp,
|
|
48
|
+
open,
|
|
49
|
+
high,
|
|
50
|
+
low,
|
|
51
|
+
close,
|
|
52
|
+
volume,
|
|
53
|
+
}));
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const plots = await run(
|
|
58
|
+
File.fromPath("timeframe_4h.pine"),
|
|
59
|
+
{
|
|
60
|
+
symbol: "BTCUSDT",
|
|
61
|
+
timeframe: "4h",
|
|
62
|
+
limit: 60,
|
|
63
|
+
},
|
|
64
|
+
"binance_exchange",
|
|
65
|
+
new Date("2025-09-23T23:00:00.000Z"),
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
console.log(await toMarkdown(SIGNAL_ID, plots, SIGNAL_SCHEMA));
|