@backtest-kit/cli 7.3.1 → 7.5.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 +153 -0
- package/build/index.cjs +296 -26
- package/build/index.mjs +297 -27
- package/package.json +13 -13
- package/template/project/package.mustache +5 -5
- package/template/signal-info.mustache +20 -20
- package/types.d.ts +35 -15
package/build/index.cjs
CHANGED
|
@@ -570,6 +570,22 @@ const getArgs = functoolsKit.singleshot(() => {
|
|
|
570
570
|
type: "boolean",
|
|
571
571
|
default: false,
|
|
572
572
|
},
|
|
573
|
+
pnldebug: {
|
|
574
|
+
type: "boolean",
|
|
575
|
+
default: false,
|
|
576
|
+
},
|
|
577
|
+
priceopen: {
|
|
578
|
+
type: "string",
|
|
579
|
+
default: "",
|
|
580
|
+
},
|
|
581
|
+
direction: {
|
|
582
|
+
type: "string",
|
|
583
|
+
default: "",
|
|
584
|
+
},
|
|
585
|
+
minutes: {
|
|
586
|
+
type: "string",
|
|
587
|
+
default: "",
|
|
588
|
+
},
|
|
573
589
|
init: {
|
|
574
590
|
type: "boolean",
|
|
575
591
|
default: false,
|
|
@@ -716,11 +732,11 @@ class SetupUtils {
|
|
|
716
732
|
BacktestKit.Markdown.enable();
|
|
717
733
|
BacktestKit.Report.enable();
|
|
718
734
|
BacktestKit.Dump.enable();
|
|
735
|
+
BacktestKit.State.enable();
|
|
719
736
|
BacktestKit.Memory.enable();
|
|
720
737
|
}
|
|
721
738
|
{
|
|
722
739
|
BacktestKit.Dump.useMarkdown();
|
|
723
|
-
BacktestKit.Memory.usePersist();
|
|
724
740
|
}
|
|
725
741
|
{
|
|
726
742
|
BacktestKit.StorageLive.usePersist();
|
|
@@ -734,6 +750,18 @@ class SetupUtils {
|
|
|
734
750
|
BacktestKit.NotificationLive.usePersist();
|
|
735
751
|
BacktestKit.NotificationBacktest.useMemory();
|
|
736
752
|
}
|
|
753
|
+
{
|
|
754
|
+
BacktestKit.RecentLive.usePersist();
|
|
755
|
+
BacktestKit.RecentBacktest.useMemory();
|
|
756
|
+
}
|
|
757
|
+
{
|
|
758
|
+
BacktestKit.MemoryLive.usePersist();
|
|
759
|
+
BacktestKit.MemoryBacktest.useLocal();
|
|
760
|
+
}
|
|
761
|
+
{
|
|
762
|
+
BacktestKit.StateLive.usePersist();
|
|
763
|
+
BacktestKit.StateBacktest.useLocal();
|
|
764
|
+
}
|
|
737
765
|
{
|
|
738
766
|
BacktestKit.Markdown.useDummy();
|
|
739
767
|
BacktestKit.Log.useJsonl();
|
|
@@ -776,6 +804,7 @@ class SetupUtils {
|
|
|
776
804
|
BacktestKit.PersistIntervalAdapter.clear();
|
|
777
805
|
BacktestKit.PersistMemoryAdapter.clear();
|
|
778
806
|
BacktestKit.PersistRecentAdapter.clear();
|
|
807
|
+
BacktestKit.PersistStateAdapter.clear();
|
|
779
808
|
}
|
|
780
809
|
{
|
|
781
810
|
BacktestKit.Dump.clear();
|
|
@@ -1929,6 +1958,9 @@ class TelegramLogicService {
|
|
|
1929
1958
|
event,
|
|
1930
1959
|
});
|
|
1931
1960
|
const markdown = await this.telegramTemplateService.getTrailingTakeMarkdown(event);
|
|
1961
|
+
if (!markdown) {
|
|
1962
|
+
return;
|
|
1963
|
+
}
|
|
1932
1964
|
await this.telegramWebService.publishNotify({
|
|
1933
1965
|
symbol: event.symbol,
|
|
1934
1966
|
markdown,
|
|
@@ -1939,6 +1971,9 @@ class TelegramLogicService {
|
|
|
1939
1971
|
event,
|
|
1940
1972
|
});
|
|
1941
1973
|
const markdown = await this.telegramTemplateService.getTrailingStopMarkdown(event);
|
|
1974
|
+
if (!markdown) {
|
|
1975
|
+
return;
|
|
1976
|
+
}
|
|
1942
1977
|
await this.telegramWebService.publishNotify({
|
|
1943
1978
|
symbol: event.symbol,
|
|
1944
1979
|
markdown,
|
|
@@ -1949,6 +1984,9 @@ class TelegramLogicService {
|
|
|
1949
1984
|
event,
|
|
1950
1985
|
});
|
|
1951
1986
|
const markdown = await this.telegramTemplateService.getBreakevenMarkdown(event);
|
|
1987
|
+
if (!markdown) {
|
|
1988
|
+
return;
|
|
1989
|
+
}
|
|
1952
1990
|
await this.telegramWebService.publishNotify({
|
|
1953
1991
|
symbol: event.symbol,
|
|
1954
1992
|
markdown,
|
|
@@ -1959,6 +1997,9 @@ class TelegramLogicService {
|
|
|
1959
1997
|
event,
|
|
1960
1998
|
});
|
|
1961
1999
|
const markdown = await this.telegramTemplateService.getPartialProfitMarkdown(event);
|
|
2000
|
+
if (!markdown) {
|
|
2001
|
+
return;
|
|
2002
|
+
}
|
|
1962
2003
|
await this.telegramWebService.publishNotify({
|
|
1963
2004
|
symbol: event.symbol,
|
|
1964
2005
|
markdown,
|
|
@@ -1969,6 +2010,9 @@ class TelegramLogicService {
|
|
|
1969
2010
|
event,
|
|
1970
2011
|
});
|
|
1971
2012
|
const markdown = await this.telegramTemplateService.getPartialLossMarkdown(event);
|
|
2013
|
+
if (!markdown) {
|
|
2014
|
+
return;
|
|
2015
|
+
}
|
|
1972
2016
|
await this.telegramWebService.publishNotify({
|
|
1973
2017
|
symbol: event.symbol,
|
|
1974
2018
|
markdown,
|
|
@@ -1979,6 +2023,9 @@ class TelegramLogicService {
|
|
|
1979
2023
|
event,
|
|
1980
2024
|
});
|
|
1981
2025
|
const markdown = await this.telegramTemplateService.getScheduledMarkdown(event);
|
|
2026
|
+
if (!markdown) {
|
|
2027
|
+
return;
|
|
2028
|
+
}
|
|
1982
2029
|
await this.telegramWebService.publishNotify({
|
|
1983
2030
|
symbol: event.symbol,
|
|
1984
2031
|
markdown,
|
|
@@ -1989,6 +2036,9 @@ class TelegramLogicService {
|
|
|
1989
2036
|
event,
|
|
1990
2037
|
});
|
|
1991
2038
|
const markdown = await this.telegramTemplateService.getCancelledMarkdown(event);
|
|
2039
|
+
if (!markdown) {
|
|
2040
|
+
return;
|
|
2041
|
+
}
|
|
1992
2042
|
await this.telegramWebService.publishNotify({
|
|
1993
2043
|
symbol: event.symbol,
|
|
1994
2044
|
markdown,
|
|
@@ -1999,6 +2049,9 @@ class TelegramLogicService {
|
|
|
1999
2049
|
event,
|
|
2000
2050
|
});
|
|
2001
2051
|
const markdown = await this.telegramTemplateService.getOpenedMarkdown(event);
|
|
2052
|
+
if (!markdown) {
|
|
2053
|
+
return;
|
|
2054
|
+
}
|
|
2002
2055
|
await this.telegramWebService.publishNotify({
|
|
2003
2056
|
symbol: event.symbol,
|
|
2004
2057
|
markdown,
|
|
@@ -2009,6 +2062,9 @@ class TelegramLogicService {
|
|
|
2009
2062
|
event,
|
|
2010
2063
|
});
|
|
2011
2064
|
const markdown = await this.telegramTemplateService.getClosedMarkdown(event);
|
|
2065
|
+
if (!markdown) {
|
|
2066
|
+
return;
|
|
2067
|
+
}
|
|
2012
2068
|
await this.telegramWebService.publishNotify({
|
|
2013
2069
|
symbol: event.symbol,
|
|
2014
2070
|
markdown,
|
|
@@ -2019,6 +2075,9 @@ class TelegramLogicService {
|
|
|
2019
2075
|
event,
|
|
2020
2076
|
});
|
|
2021
2077
|
const markdown = await this.telegramTemplateService.getRiskMarkdown(event);
|
|
2078
|
+
if (!markdown) {
|
|
2079
|
+
return;
|
|
2080
|
+
}
|
|
2022
2081
|
await this.telegramWebService.publishNotify({
|
|
2023
2082
|
symbol: event.symbol,
|
|
2024
2083
|
markdown,
|
|
@@ -2029,6 +2088,9 @@ class TelegramLogicService {
|
|
|
2029
2088
|
event,
|
|
2030
2089
|
});
|
|
2031
2090
|
const markdown = await this.telegramTemplateService.getAverageBuyMarkdown(event);
|
|
2091
|
+
if (!markdown) {
|
|
2092
|
+
return;
|
|
2093
|
+
}
|
|
2032
2094
|
await this.telegramWebService.publishNotify({
|
|
2033
2095
|
symbol: event.symbol,
|
|
2034
2096
|
markdown,
|
|
@@ -2039,6 +2101,9 @@ class TelegramLogicService {
|
|
|
2039
2101
|
event,
|
|
2040
2102
|
});
|
|
2041
2103
|
const markdown = await this.telegramTemplateService.getSignalOpenMarkdown(event);
|
|
2104
|
+
if (!markdown) {
|
|
2105
|
+
return;
|
|
2106
|
+
}
|
|
2042
2107
|
await this.telegramWebService.publishNotify({
|
|
2043
2108
|
symbol: event.symbol,
|
|
2044
2109
|
markdown,
|
|
@@ -2049,6 +2114,9 @@ class TelegramLogicService {
|
|
|
2049
2114
|
event,
|
|
2050
2115
|
});
|
|
2051
2116
|
const markdown = await this.telegramTemplateService.getSignalCloseMarkdown(event);
|
|
2117
|
+
if (!markdown) {
|
|
2118
|
+
return;
|
|
2119
|
+
}
|
|
2052
2120
|
await this.telegramWebService.publishNotify({
|
|
2053
2121
|
symbol: event.symbol,
|
|
2054
2122
|
markdown,
|
|
@@ -2059,6 +2127,9 @@ class TelegramLogicService {
|
|
|
2059
2127
|
event,
|
|
2060
2128
|
});
|
|
2061
2129
|
const markdown = await this.telegramTemplateService.getSignalInfoMarkdown(event);
|
|
2130
|
+
if (!markdown) {
|
|
2131
|
+
return;
|
|
2132
|
+
}
|
|
2062
2133
|
await this.telegramWebService.publishNotify({
|
|
2063
2134
|
symbol: event.symbol,
|
|
2064
2135
|
markdown,
|
|
@@ -2069,6 +2140,9 @@ class TelegramLogicService {
|
|
|
2069
2140
|
event,
|
|
2070
2141
|
});
|
|
2071
2142
|
const markdown = await this.telegramTemplateService.getCancelScheduledMarkdown(event);
|
|
2143
|
+
if (!markdown) {
|
|
2144
|
+
return;
|
|
2145
|
+
}
|
|
2072
2146
|
await this.telegramWebService.publishNotify({
|
|
2073
2147
|
symbol: event.symbol,
|
|
2074
2148
|
markdown,
|
|
@@ -2079,6 +2153,9 @@ class TelegramLogicService {
|
|
|
2079
2153
|
event,
|
|
2080
2154
|
});
|
|
2081
2155
|
const markdown = await this.telegramTemplateService.getClosePendingMarkdown(event);
|
|
2156
|
+
if (!markdown) {
|
|
2157
|
+
return;
|
|
2158
|
+
}
|
|
2082
2159
|
await this.telegramWebService.publishNotify({
|
|
2083
2160
|
symbol: event.symbol,
|
|
2084
2161
|
markdown,
|
|
@@ -2180,104 +2257,182 @@ const RENDER_TEMPLATE_FN = async (fileName, event, self) => {
|
|
|
2180
2257
|
const template = await READ_TEMPLATE_FN(fileName, self);
|
|
2181
2258
|
return Mustache.render(template, event);
|
|
2182
2259
|
};
|
|
2260
|
+
const GET_TELEGRAM_CONFIG_FN = async (self) => {
|
|
2261
|
+
const exports = await self.configConnectionService.loadConfig("telegram.config");
|
|
2262
|
+
if (!exports) {
|
|
2263
|
+
return null;
|
|
2264
|
+
}
|
|
2265
|
+
return "default" in exports
|
|
2266
|
+
? exports.default
|
|
2267
|
+
: exports;
|
|
2268
|
+
};
|
|
2183
2269
|
class TelegramTemplateService {
|
|
2184
2270
|
constructor() {
|
|
2185
2271
|
this.loggerService = inject(TYPES.loggerService);
|
|
2186
2272
|
this.resolveService = inject(TYPES.resolveService);
|
|
2273
|
+
this.configConnectionService = inject(TYPES.configConnectionService);
|
|
2274
|
+
this.getTelegramAdapter = functoolsKit.singleshot(async () => {
|
|
2275
|
+
this.loggerService.log("telegramTemplateService getTelegramAdapter");
|
|
2276
|
+
return await GET_TELEGRAM_CONFIG_FN(this);
|
|
2277
|
+
});
|
|
2187
2278
|
this.getTrailingTakeMarkdown = async (event) => {
|
|
2188
2279
|
this.loggerService.log("telegramTemplateService getTrailingTakeMarkdown", {
|
|
2189
2280
|
event,
|
|
2190
2281
|
});
|
|
2282
|
+
const adapter = await this.getTelegramAdapter();
|
|
2283
|
+
if (adapter?.getTrailingTakeMarkdown) {
|
|
2284
|
+
return await adapter.getTrailingTakeMarkdown(event);
|
|
2285
|
+
}
|
|
2191
2286
|
return await RENDER_TEMPLATE_FN("trailing-take.mustache", event, this);
|
|
2192
2287
|
};
|
|
2193
2288
|
this.getTrailingStopMarkdown = async (event) => {
|
|
2194
2289
|
this.loggerService.log("telegramTemplateService getTrailingStopMarkdown", {
|
|
2195
2290
|
event,
|
|
2196
2291
|
});
|
|
2292
|
+
const adapter = await this.getTelegramAdapter();
|
|
2293
|
+
if (adapter?.getTrailingStopMarkdown) {
|
|
2294
|
+
return await adapter.getTrailingStopMarkdown(event);
|
|
2295
|
+
}
|
|
2197
2296
|
return await RENDER_TEMPLATE_FN("trailing-stop.mustache", event, this);
|
|
2198
2297
|
};
|
|
2199
2298
|
this.getBreakevenMarkdown = async (event) => {
|
|
2200
2299
|
this.loggerService.log("telegramTemplateService getBreakevenMarkdown", {
|
|
2201
2300
|
event,
|
|
2202
2301
|
});
|
|
2302
|
+
const adapter = await this.getTelegramAdapter();
|
|
2303
|
+
if (adapter?.getBreakevenMarkdown) {
|
|
2304
|
+
return await adapter.getBreakevenMarkdown(event);
|
|
2305
|
+
}
|
|
2203
2306
|
return await RENDER_TEMPLATE_FN("breakeven.mustache", event, this);
|
|
2204
2307
|
};
|
|
2205
2308
|
this.getPartialProfitMarkdown = async (event) => {
|
|
2206
2309
|
this.loggerService.log("telegramTemplateService getPartialProfitMarkdown", {
|
|
2207
2310
|
event,
|
|
2208
2311
|
});
|
|
2312
|
+
const adapter = await this.getTelegramAdapter();
|
|
2313
|
+
if (adapter?.getPartialProfitMarkdown) {
|
|
2314
|
+
return await adapter.getPartialProfitMarkdown(event);
|
|
2315
|
+
}
|
|
2209
2316
|
return await RENDER_TEMPLATE_FN("partial-profit.mustache", event, this);
|
|
2210
2317
|
};
|
|
2211
2318
|
this.getPartialLossMarkdown = async (event) => {
|
|
2212
2319
|
this.loggerService.log("telegramTemplateService getPartialLossMarkdown", {
|
|
2213
2320
|
event,
|
|
2214
2321
|
});
|
|
2322
|
+
const adapter = await this.getTelegramAdapter();
|
|
2323
|
+
if (adapter?.getPartialLossMarkdown) {
|
|
2324
|
+
return await adapter.getPartialLossMarkdown(event);
|
|
2325
|
+
}
|
|
2215
2326
|
return await RENDER_TEMPLATE_FN("partial-loss.mustache", event, this);
|
|
2216
2327
|
};
|
|
2217
2328
|
this.getScheduledMarkdown = async (event) => {
|
|
2218
2329
|
this.loggerService.log("telegramTemplateService getScheduledMarkdown", {
|
|
2219
2330
|
event,
|
|
2220
2331
|
});
|
|
2332
|
+
const adapter = await this.getTelegramAdapter();
|
|
2333
|
+
if (adapter?.getScheduledMarkdown) {
|
|
2334
|
+
return await adapter.getScheduledMarkdown(event);
|
|
2335
|
+
}
|
|
2221
2336
|
return await RENDER_TEMPLATE_FN("scheduled.mustache", event, this);
|
|
2222
2337
|
};
|
|
2223
2338
|
this.getCancelledMarkdown = async (event) => {
|
|
2224
2339
|
this.loggerService.log("telegramTemplateService getCancelledMarkdown", {
|
|
2225
2340
|
event,
|
|
2226
2341
|
});
|
|
2342
|
+
const adapter = await this.getTelegramAdapter();
|
|
2343
|
+
if (adapter?.getCancelledMarkdown) {
|
|
2344
|
+
return await adapter.getCancelledMarkdown(event);
|
|
2345
|
+
}
|
|
2227
2346
|
return await RENDER_TEMPLATE_FN("cancelled.mustache", event, this);
|
|
2228
2347
|
};
|
|
2229
2348
|
this.getOpenedMarkdown = async (event) => {
|
|
2230
2349
|
this.loggerService.log("telegramTemplateService getOpenedMarkdown", {
|
|
2231
2350
|
event,
|
|
2232
2351
|
});
|
|
2352
|
+
const adapter = await this.getTelegramAdapter();
|
|
2353
|
+
if (adapter?.getOpenedMarkdown) {
|
|
2354
|
+
return await adapter.getOpenedMarkdown(event);
|
|
2355
|
+
}
|
|
2233
2356
|
return await RENDER_TEMPLATE_FN("opened.mustache", event, this);
|
|
2234
2357
|
};
|
|
2235
2358
|
this.getClosedMarkdown = async (event) => {
|
|
2236
2359
|
this.loggerService.log("telegramTemplateService getClosedMarkdown", {
|
|
2237
2360
|
event,
|
|
2238
2361
|
});
|
|
2362
|
+
const adapter = await this.getTelegramAdapter();
|
|
2363
|
+
if (adapter?.getClosedMarkdown) {
|
|
2364
|
+
return await adapter.getClosedMarkdown(event);
|
|
2365
|
+
}
|
|
2239
2366
|
return await RENDER_TEMPLATE_FN("closed.mustache", event, this);
|
|
2240
2367
|
};
|
|
2241
2368
|
this.getRiskMarkdown = async (event) => {
|
|
2242
2369
|
this.loggerService.log("telegramTemplateService getRiskMarkdown", {
|
|
2243
2370
|
event,
|
|
2244
2371
|
});
|
|
2372
|
+
const adapter = await this.getTelegramAdapter();
|
|
2373
|
+
if (adapter?.getRiskMarkdown) {
|
|
2374
|
+
return await adapter.getRiskMarkdown(event);
|
|
2375
|
+
}
|
|
2245
2376
|
return await RENDER_TEMPLATE_FN("risk.mustache", event, this);
|
|
2246
2377
|
};
|
|
2247
2378
|
this.getAverageBuyMarkdown = async (event) => {
|
|
2248
2379
|
this.loggerService.log("telegramTemplateService getAverageBuyMarkdown", {
|
|
2249
2380
|
event,
|
|
2250
2381
|
});
|
|
2382
|
+
const adapter = await this.getTelegramAdapter();
|
|
2383
|
+
if (adapter?.getAverageBuyMarkdown) {
|
|
2384
|
+
return await adapter.getAverageBuyMarkdown(event);
|
|
2385
|
+
}
|
|
2251
2386
|
return await RENDER_TEMPLATE_FN("average-buy.mustache", event, this);
|
|
2252
2387
|
};
|
|
2253
2388
|
this.getSignalOpenMarkdown = async (event) => {
|
|
2254
2389
|
this.loggerService.log("telegramTemplateService getSignalOpenMarkdown", {
|
|
2255
2390
|
event,
|
|
2256
2391
|
});
|
|
2392
|
+
const adapter = await this.getTelegramAdapter();
|
|
2393
|
+
if (adapter?.getSignalOpenMarkdown) {
|
|
2394
|
+
return await adapter.getSignalOpenMarkdown(event);
|
|
2395
|
+
}
|
|
2257
2396
|
return await RENDER_TEMPLATE_FN("signal-open.mustache", event, this);
|
|
2258
2397
|
};
|
|
2259
2398
|
this.getSignalCloseMarkdown = async (event) => {
|
|
2260
2399
|
this.loggerService.log("telegramTemplateService getSignalCloseMarkdown", {
|
|
2261
2400
|
event,
|
|
2262
2401
|
});
|
|
2402
|
+
const adapter = await this.getTelegramAdapter();
|
|
2403
|
+
if (adapter?.getSignalCloseMarkdown) {
|
|
2404
|
+
return await adapter.getSignalCloseMarkdown(event);
|
|
2405
|
+
}
|
|
2263
2406
|
return await RENDER_TEMPLATE_FN("signal-close.mustache", event, this);
|
|
2264
2407
|
};
|
|
2265
2408
|
this.getCancelScheduledMarkdown = async (event) => {
|
|
2266
2409
|
this.loggerService.log("telegramTemplateService getCancelScheduledMarkdown", {
|
|
2267
2410
|
event,
|
|
2268
2411
|
});
|
|
2412
|
+
const adapter = await this.getTelegramAdapter();
|
|
2413
|
+
if (adapter?.getCancelScheduledMarkdown) {
|
|
2414
|
+
return await adapter.getCancelScheduledMarkdown(event);
|
|
2415
|
+
}
|
|
2269
2416
|
return await RENDER_TEMPLATE_FN("cancel-scheduled.mustache", event, this);
|
|
2270
2417
|
};
|
|
2271
2418
|
this.getClosePendingMarkdown = async (event) => {
|
|
2272
2419
|
this.loggerService.log("telegramTemplateService getClosePendingMarkdown", {
|
|
2273
2420
|
event,
|
|
2274
2421
|
});
|
|
2422
|
+
const adapter = await this.getTelegramAdapter();
|
|
2423
|
+
if (adapter?.getClosePendingMarkdown) {
|
|
2424
|
+
return await adapter.getClosePendingMarkdown(event);
|
|
2425
|
+
}
|
|
2275
2426
|
return await RENDER_TEMPLATE_FN("close-pending.mustache", event, this);
|
|
2276
2427
|
};
|
|
2277
2428
|
this.getSignalInfoMarkdown = async (event) => {
|
|
2278
2429
|
this.loggerService.log("telegramTemplateService getSignalInfoMarkdown", {
|
|
2279
2430
|
event,
|
|
2280
2431
|
});
|
|
2432
|
+
const adapter = await this.getTelegramAdapter();
|
|
2433
|
+
if (adapter?.getSignalInfoMarkdown) {
|
|
2434
|
+
return await adapter.getSignalInfoMarkdown(event);
|
|
2435
|
+
}
|
|
2281
2436
|
return await RENDER_TEMPLATE_FN("signal-info.mustache", event, this);
|
|
2282
2437
|
};
|
|
2283
2438
|
}
|
|
@@ -2839,14 +2994,14 @@ const cli = {
|
|
|
2839
2994
|
};
|
|
2840
2995
|
init();
|
|
2841
2996
|
|
|
2842
|
-
const MODES = ["backtest", "walker", "paper", "live", "pine", "editor", "dump", "flush", "init", "help", "version"];
|
|
2997
|
+
const MODES = ["backtest", "walker", "paper", "live", "pine", "editor", "dump", "pnldebug", "flush", "init", "help", "version"];
|
|
2843
2998
|
const ENTRY_PATH$1 = "./node_modules/@backtest-kit/cli/build/index.mjs";
|
|
2844
2999
|
const HELP_TEXT$1 = `
|
|
2845
3000
|
Example:
|
|
2846
3001
|
|
|
2847
3002
|
node ${ENTRY_PATH$1} --help
|
|
2848
3003
|
`.trimStart();
|
|
2849
|
-
const main$
|
|
3004
|
+
const main$e = async () => {
|
|
2850
3005
|
if (!getEntry((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))) {
|
|
2851
3006
|
return;
|
|
2852
3007
|
}
|
|
@@ -2854,14 +3009,14 @@ const main$d = async () => {
|
|
|
2854
3009
|
if (MODES.some((mode) => values[mode])) {
|
|
2855
3010
|
return;
|
|
2856
3011
|
}
|
|
2857
|
-
process.stdout.write(`@backtest-kit/cli ${"7.
|
|
3012
|
+
process.stdout.write(`@backtest-kit/cli ${"7.5.0"}\n`);
|
|
2858
3013
|
process.stdout.write("\n");
|
|
2859
3014
|
process.stdout.write(`Run with --help to see available commands.\n`);
|
|
2860
3015
|
process.stdout.write("\n");
|
|
2861
3016
|
process.stdout.write(HELP_TEXT$1);
|
|
2862
3017
|
process.exit(0);
|
|
2863
3018
|
};
|
|
2864
|
-
main$
|
|
3019
|
+
main$e();
|
|
2865
3020
|
|
|
2866
3021
|
const notifyShutdown = functoolsKit.singleshot(async () => {
|
|
2867
3022
|
console.log("Graceful shutdown initiated. Press Ctrl+C again to force quit.");
|
|
@@ -2877,7 +3032,7 @@ const flush = async (entryPoint) => {
|
|
|
2877
3032
|
console.log(`Removed: ${target}`);
|
|
2878
3033
|
}
|
|
2879
3034
|
};
|
|
2880
|
-
const main$
|
|
3035
|
+
const main$d = async () => {
|
|
2881
3036
|
if (!getEntry((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))) {
|
|
2882
3037
|
return;
|
|
2883
3038
|
}
|
|
@@ -2894,7 +3049,7 @@ const main$c = async () => {
|
|
|
2894
3049
|
}
|
|
2895
3050
|
process.exit(0);
|
|
2896
3051
|
};
|
|
2897
|
-
main$
|
|
3052
|
+
main$d();
|
|
2898
3053
|
|
|
2899
3054
|
const BEFORE_EXIT_FN$5 = functoolsKit.singleshot(async () => {
|
|
2900
3055
|
process.off("SIGINT", BEFORE_EXIT_FN$5);
|
|
@@ -2916,7 +3071,7 @@ const BEFORE_EXIT_FN$5 = functoolsKit.singleshot(async () => {
|
|
|
2916
3071
|
const listenGracefulShutdown$5 = functoolsKit.singleshot(() => {
|
|
2917
3072
|
process.on("SIGINT", BEFORE_EXIT_FN$5);
|
|
2918
3073
|
});
|
|
2919
|
-
const main$
|
|
3074
|
+
const main$c = async () => {
|
|
2920
3075
|
if (!getEntry((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))) {
|
|
2921
3076
|
return;
|
|
2922
3077
|
}
|
|
@@ -2931,7 +3086,7 @@ const main$b = async () => {
|
|
|
2931
3086
|
await cli.backtestMainService.connect();
|
|
2932
3087
|
listenGracefulShutdown$5();
|
|
2933
3088
|
};
|
|
2934
|
-
main$
|
|
3089
|
+
main$c();
|
|
2935
3090
|
|
|
2936
3091
|
const BEFORE_EXIT_FN$4 = functoolsKit.singleshot(async () => {
|
|
2937
3092
|
process.off("SIGINT", BEFORE_EXIT_FN$4);
|
|
@@ -2949,7 +3104,7 @@ const BEFORE_EXIT_FN$4 = functoolsKit.singleshot(async () => {
|
|
|
2949
3104
|
const listenGracefulShutdown$4 = functoolsKit.singleshot(() => {
|
|
2950
3105
|
process.on("SIGINT", BEFORE_EXIT_FN$4);
|
|
2951
3106
|
});
|
|
2952
|
-
const main$
|
|
3107
|
+
const main$b = async () => {
|
|
2953
3108
|
if (!getEntry((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))) {
|
|
2954
3109
|
return;
|
|
2955
3110
|
}
|
|
@@ -2965,7 +3120,7 @@ const main$a = async () => {
|
|
|
2965
3120
|
listenGracefulShutdown$4();
|
|
2966
3121
|
await cli.walkerMainService.connect();
|
|
2967
3122
|
};
|
|
2968
|
-
main$
|
|
3123
|
+
main$b();
|
|
2969
3124
|
|
|
2970
3125
|
const BEFORE_EXIT_FN$3 = functoolsKit.singleshot(async () => {
|
|
2971
3126
|
process.off("SIGINT", BEFORE_EXIT_FN$3);
|
|
@@ -2986,7 +3141,7 @@ const BEFORE_EXIT_FN$3 = functoolsKit.singleshot(async () => {
|
|
|
2986
3141
|
const listenGracefulShutdown$3 = functoolsKit.singleshot(() => {
|
|
2987
3142
|
process.on("SIGINT", BEFORE_EXIT_FN$3);
|
|
2988
3143
|
});
|
|
2989
|
-
const main$
|
|
3144
|
+
const main$a = async () => {
|
|
2990
3145
|
if (!getEntry((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))) {
|
|
2991
3146
|
return;
|
|
2992
3147
|
}
|
|
@@ -2997,7 +3152,7 @@ const main$9 = async () => {
|
|
|
2997
3152
|
cli.paperMainService.connect();
|
|
2998
3153
|
listenGracefulShutdown$3();
|
|
2999
3154
|
};
|
|
3000
|
-
main$
|
|
3155
|
+
main$a();
|
|
3001
3156
|
|
|
3002
3157
|
const BEFORE_EXIT_FN$2 = functoolsKit.singleshot(async () => {
|
|
3003
3158
|
process.off("SIGINT", BEFORE_EXIT_FN$2);
|
|
@@ -3018,7 +3173,7 @@ const BEFORE_EXIT_FN$2 = functoolsKit.singleshot(async () => {
|
|
|
3018
3173
|
const listenGracefulShutdown$2 = functoolsKit.singleshot(() => {
|
|
3019
3174
|
process.on("SIGINT", BEFORE_EXIT_FN$2);
|
|
3020
3175
|
});
|
|
3021
|
-
const main$
|
|
3176
|
+
const main$9 = async () => {
|
|
3022
3177
|
if (!getEntry((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))) {
|
|
3023
3178
|
return;
|
|
3024
3179
|
}
|
|
@@ -3029,7 +3184,7 @@ const main$8 = async () => {
|
|
|
3029
3184
|
await cli.liveMainService.connect();
|
|
3030
3185
|
listenGracefulShutdown$2();
|
|
3031
3186
|
};
|
|
3032
|
-
main$
|
|
3187
|
+
main$9();
|
|
3033
3188
|
|
|
3034
3189
|
const BEFORE_EXIT_FN$1 = functoolsKit.singleshot(async () => {
|
|
3035
3190
|
process.off("SIGINT", BEFORE_EXIT_FN$1);
|
|
@@ -3039,7 +3194,7 @@ const BEFORE_EXIT_FN$1 = functoolsKit.singleshot(async () => {
|
|
|
3039
3194
|
const listenGracefulShutdown$1 = functoolsKit.singleshot(() => {
|
|
3040
3195
|
process.on("SIGINT", BEFORE_EXIT_FN$1);
|
|
3041
3196
|
});
|
|
3042
|
-
const main$
|
|
3197
|
+
const main$8 = async () => {
|
|
3043
3198
|
if (!getEntry((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))) {
|
|
3044
3199
|
return;
|
|
3045
3200
|
}
|
|
@@ -3049,7 +3204,7 @@ const main$7 = async () => {
|
|
|
3049
3204
|
}
|
|
3050
3205
|
listenGracefulShutdown$1();
|
|
3051
3206
|
};
|
|
3052
|
-
main$
|
|
3207
|
+
main$8();
|
|
3053
3208
|
|
|
3054
3209
|
const BEFORE_EXIT_FN = functoolsKit.singleshot(async () => {
|
|
3055
3210
|
process.off("SIGINT", BEFORE_EXIT_FN);
|
|
@@ -3059,7 +3214,7 @@ const BEFORE_EXIT_FN = functoolsKit.singleshot(async () => {
|
|
|
3059
3214
|
const listenGracefulShutdown = functoolsKit.singleshot(() => {
|
|
3060
3215
|
process.on("SIGINT", BEFORE_EXIT_FN);
|
|
3061
3216
|
});
|
|
3062
|
-
const main$
|
|
3217
|
+
const main$7 = async () => {
|
|
3063
3218
|
if (!getEntry((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))) {
|
|
3064
3219
|
return;
|
|
3065
3220
|
}
|
|
@@ -3069,7 +3224,7 @@ const main$6 = async () => {
|
|
|
3069
3224
|
}
|
|
3070
3225
|
listenGracefulShutdown();
|
|
3071
3226
|
};
|
|
3072
|
-
main$
|
|
3227
|
+
main$7();
|
|
3073
3228
|
|
|
3074
3229
|
const EXTRACT_ROWS_FN = (plots, schema) => {
|
|
3075
3230
|
const keys = Object.keys(schema);
|
|
@@ -3091,7 +3246,7 @@ const EXTRACT_ROWS_FN = (plots, schema) => {
|
|
|
3091
3246
|
}
|
|
3092
3247
|
return rows;
|
|
3093
3248
|
};
|
|
3094
|
-
const main$
|
|
3249
|
+
const main$6 = async () => {
|
|
3095
3250
|
if (!getEntry((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))) {
|
|
3096
3251
|
return;
|
|
3097
3252
|
}
|
|
@@ -3171,9 +3326,9 @@ const main$5 = async () => {
|
|
|
3171
3326
|
console.log(await BacktestKitPinets.toMarkdown(signalId, plots, signalSchema));
|
|
3172
3327
|
process.exit(0);
|
|
3173
3328
|
};
|
|
3174
|
-
main$
|
|
3329
|
+
main$6();
|
|
3175
3330
|
|
|
3176
|
-
const main$
|
|
3331
|
+
const main$5 = async () => {
|
|
3177
3332
|
if (!getEntry((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))) {
|
|
3178
3333
|
return;
|
|
3179
3334
|
}
|
|
@@ -3208,9 +3363,9 @@ const main$4 = async () => {
|
|
|
3208
3363
|
};
|
|
3209
3364
|
process.on("SIGINT", beforeExit);
|
|
3210
3365
|
};
|
|
3211
|
-
main$
|
|
3366
|
+
main$5();
|
|
3212
3367
|
|
|
3213
|
-
const main$
|
|
3368
|
+
const main$4 = async () => {
|
|
3214
3369
|
if (!getEntry((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))) {
|
|
3215
3370
|
return;
|
|
3216
3371
|
}
|
|
@@ -3271,6 +3426,102 @@ const main$3 = async () => {
|
|
|
3271
3426
|
console.log(JSON.stringify(candles, null, 2));
|
|
3272
3427
|
process.exit(0);
|
|
3273
3428
|
};
|
|
3429
|
+
main$4();
|
|
3430
|
+
|
|
3431
|
+
const main$3 = async () => {
|
|
3432
|
+
if (!getEntry((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))) {
|
|
3433
|
+
return;
|
|
3434
|
+
}
|
|
3435
|
+
const { values } = getArgs();
|
|
3436
|
+
if (!values.pnldebug) {
|
|
3437
|
+
return;
|
|
3438
|
+
}
|
|
3439
|
+
await cli.moduleConnectionService.loadModule("./pnldebug.module");
|
|
3440
|
+
{
|
|
3441
|
+
await cli.exchangeSchemaService.addSchema();
|
|
3442
|
+
await cli.symbolSchemaService.addSchema();
|
|
3443
|
+
}
|
|
3444
|
+
const [defaultExchangeName = null] = await BacktestKit.listExchangeSchema();
|
|
3445
|
+
const exchangeName = values.exchange || defaultExchangeName?.exchangeName;
|
|
3446
|
+
const symbol = values.symbol || "BTCUSDT";
|
|
3447
|
+
const priceOpenStr = values.priceopen;
|
|
3448
|
+
if (!priceOpenStr) {
|
|
3449
|
+
console.error("Error: --priceopen is required");
|
|
3450
|
+
process.exit(1);
|
|
3451
|
+
}
|
|
3452
|
+
const priceOpen = parseFloat(priceOpenStr);
|
|
3453
|
+
if (isNaN(priceOpen)) {
|
|
3454
|
+
console.error(`Error: --priceopen must be a number, got: ${priceOpenStr}`);
|
|
3455
|
+
process.exit(1);
|
|
3456
|
+
}
|
|
3457
|
+
const direction = (values.direction || "long").toLowerCase();
|
|
3458
|
+
if (direction !== "long" && direction !== "short") {
|
|
3459
|
+
console.error(`Error: --direction must be 'long' or 'short', got: ${direction}`);
|
|
3460
|
+
process.exit(1);
|
|
3461
|
+
}
|
|
3462
|
+
const whenStr = values.when || Date.now().toString();
|
|
3463
|
+
const whenStamp = Date.parse(whenStr);
|
|
3464
|
+
const when = isNaN(whenStamp) ? new Date() : new Date(whenStamp);
|
|
3465
|
+
const timestamp = BacktestKit.alignToInterval(when, "1m").getTime();
|
|
3466
|
+
const minutesStr = values.minutes || "60";
|
|
3467
|
+
const minutesNum = parseInt(minutesStr);
|
|
3468
|
+
const minutes = isNaN(minutesNum) ? 60 : minutesNum;
|
|
3469
|
+
const candles = await BacktestKit.Exchange.getRawCandles(symbol, "1m", { exchangeName }, minutes, undefined, timestamp);
|
|
3470
|
+
if (candles.length === 0) {
|
|
3471
|
+
console.error("Error: no candles returned for the given parameters");
|
|
3472
|
+
process.exit(1);
|
|
3473
|
+
}
|
|
3474
|
+
let peak = 0;
|
|
3475
|
+
let drawdown = 0;
|
|
3476
|
+
const rows = candles.map((c, i) => {
|
|
3477
|
+
const pnl = direction === "short"
|
|
3478
|
+
? (priceOpen - c.close) / priceOpen * 100
|
|
3479
|
+
: (c.close - priceOpen) / priceOpen * 100;
|
|
3480
|
+
if (pnl > peak)
|
|
3481
|
+
peak = pnl;
|
|
3482
|
+
if (pnl < drawdown)
|
|
3483
|
+
drawdown = pnl;
|
|
3484
|
+
return { min: i + 1, timestamp: c.timestamp, close: c.close, pnl, peak, drawdown };
|
|
3485
|
+
});
|
|
3486
|
+
const dumpName = values.output || `${symbol}_${direction}_${priceOpen}_${timestamp}`;
|
|
3487
|
+
const dumpDir = path.join(process.cwd(), "dump");
|
|
3488
|
+
if (values.json) {
|
|
3489
|
+
const filePath = path.resolve(dumpDir, `${dumpName}.json`);
|
|
3490
|
+
await fs$1.mkdir(dumpDir, { recursive: true });
|
|
3491
|
+
await fs$1.writeFile(filePath, JSON.stringify(rows, null, 2), "utf-8");
|
|
3492
|
+
console.log(`Saved: ${filePath}`);
|
|
3493
|
+
process.exit(0);
|
|
3494
|
+
}
|
|
3495
|
+
if (values.jsonl) {
|
|
3496
|
+
const filePath = path.resolve(dumpDir, `${dumpName}.jsonl`);
|
|
3497
|
+
await fs$1.mkdir(dumpDir, { recursive: true });
|
|
3498
|
+
await fs$1.writeFile(filePath, rows.map((r) => JSON.stringify(r)).join("\n"), "utf-8");
|
|
3499
|
+
console.log(`Saved: ${filePath}`);
|
|
3500
|
+
process.exit(0);
|
|
3501
|
+
}
|
|
3502
|
+
if (values.markdown) {
|
|
3503
|
+
const header = `| min | timestamp | close | pnl% | peak% | drawdown% |\n| --- | --- | --- | --- | --- | --- |`;
|
|
3504
|
+
const mdRows = rows.map((r) => `| ${r.min} | ${new Date(r.timestamp).toISOString()} | ${r.close.toFixed(2)} | ${(r.pnl >= 0 ? "+" : "") + r.pnl.toFixed(2)}% | +${r.peak.toFixed(2)}% | ${r.drawdown.toFixed(2)}% |`);
|
|
3505
|
+
const filePath = path.resolve(dumpDir, `${dumpName}.md`);
|
|
3506
|
+
await fs$1.mkdir(dumpDir, { recursive: true });
|
|
3507
|
+
await fs$1.writeFile(filePath, [header, ...mdRows].join("\n"), "utf-8");
|
|
3508
|
+
console.log(`Saved: ${filePath}`);
|
|
3509
|
+
process.exit(0);
|
|
3510
|
+
}
|
|
3511
|
+
console.log(`Symbol: ${symbol} | Direction: ${direction} | PriceOpen: ${priceOpen} | From: ${new Date(timestamp).toISOString()} | Minutes: ${minutes}\n`);
|
|
3512
|
+
console.log(`${"min".padStart(5)} | ${"timestamp".padEnd(24)} | ${"close".padStart(12)} | ${"pnl%".padStart(8)} | ${"peak%".padStart(8)} | ${"drawdown%".padStart(10)}`);
|
|
3513
|
+
console.log("-".repeat(83));
|
|
3514
|
+
for (const r of rows) {
|
|
3515
|
+
const min = String(r.min).padStart(5);
|
|
3516
|
+
const ts = new Date(r.timestamp).toISOString().padEnd(24);
|
|
3517
|
+
const close = r.close.toFixed(2).padStart(12);
|
|
3518
|
+
const pnlStr = (r.pnl >= 0 ? "+" : "") + r.pnl.toFixed(2) + "%";
|
|
3519
|
+
const peakStr = "+" + r.peak.toFixed(2) + "%";
|
|
3520
|
+
const drawdownStr = r.drawdown.toFixed(2) + "%";
|
|
3521
|
+
console.log(`${min} | ${ts} | ${close} | ${pnlStr.padStart(8)} | ${peakStr.padStart(8)} | ${drawdownStr.padStart(10)}`);
|
|
3522
|
+
}
|
|
3523
|
+
process.exit(0);
|
|
3524
|
+
};
|
|
3274
3525
|
main$3();
|
|
3275
3526
|
|
|
3276
3527
|
const __filename$1 = url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
|
|
@@ -3389,6 +3640,7 @@ Modes:
|
|
|
3389
3640
|
--pine <entry> Execute a local .pine indicator file
|
|
3390
3641
|
--editor Open the Pine Script visual editor in the browser
|
|
3391
3642
|
--dump Fetch and save raw OHLCV candles
|
|
3643
|
+
--pnldebug Simulate PnL per minute for a given entry price and direction
|
|
3392
3644
|
--flush <entry...> Delete report/log/markdown/agent folders from strategy dump dir
|
|
3393
3645
|
--init Scaffold a new project in the current directory
|
|
3394
3646
|
--help Print this help message
|
|
@@ -3461,6 +3713,21 @@ Candle dump flags (--dump):
|
|
|
3461
3713
|
|
|
3462
3714
|
Module file ./modules/dump.module is loaded automatically if it exists.
|
|
3463
3715
|
|
|
3716
|
+
PnL debug flags (--pnldebug):
|
|
3717
|
+
|
|
3718
|
+
--symbol <string> Trading pair (default: BTCUSDT)
|
|
3719
|
+
--priceopen <number> Entry price (required)
|
|
3720
|
+
--direction <string> Position direction: long or short (default: long)
|
|
3721
|
+
--when <string> Start timestamp — ISO 8601 or Unix ms (default: now)
|
|
3722
|
+
--minutes <string> Number of 1m candles to simulate (default: 60)
|
|
3723
|
+
--exchange <string> Exchange name (default: first registered)
|
|
3724
|
+
--output <string> Output file base name (default: {SYMBOL}_{DIRECTION}_{PRICEOPEN}_{TIMESTAMP})
|
|
3725
|
+
--json Save as JSON array to ./dump/<output>.json
|
|
3726
|
+
--jsonl Save as JSONL to ./dump/<output>.jsonl
|
|
3727
|
+
--markdown Save as Markdown table to ./dump/<output>.md
|
|
3728
|
+
|
|
3729
|
+
Module file ./modules/pnldebug.module is loaded automatically if it exists.
|
|
3730
|
+
|
|
3464
3731
|
Flush flags (--flush):
|
|
3465
3732
|
|
|
3466
3733
|
One or more positional entry points. For each entry point the following
|
|
@@ -3483,6 +3750,7 @@ Module hooks (loaded automatically by each mode):
|
|
|
3483
3750
|
modules/pine.module --pine Exchange schema for PineScript runs
|
|
3484
3751
|
modules/editor.module --editor Exchange schema for the visual Pine editor
|
|
3485
3752
|
modules/dump.module --dump Exchange schema for candle dumps
|
|
3753
|
+
modules/pnldebug.module --pnldebug Exchange schema for PnL debug runs
|
|
3486
3754
|
|
|
3487
3755
|
--flush has no associated module. It only removes dump subdirectories.
|
|
3488
3756
|
|
|
@@ -3506,6 +3774,8 @@ Examples:
|
|
|
3506
3774
|
node ${ENTRY_PATH} --pine ./math/feb_2026.pine --timeframe 15m --limit 500 --jsonl
|
|
3507
3775
|
node ${ENTRY_PATH} --editor
|
|
3508
3776
|
node ${ENTRY_PATH} --dump --symbol BTCUSDT --timeframe 15m --limit 500 --jsonl
|
|
3777
|
+
node ${ENTRY_PATH} --pnldebug --symbol BTCUSDT --priceopen 64069.50 --direction short --when "2025-02-25" --minutes 120
|
|
3778
|
+
node ${ENTRY_PATH} --pnldebug --priceopen 67956.73 --direction long --when 1772064000000 --minutes 60 --markdown
|
|
3509
3779
|
node ${ENTRY_PATH} --flush ./content/feb_2026.strategy/feb_2026.strategy.ts
|
|
3510
3780
|
node ${ENTRY_PATH} --flush ./content/feb_2026.strategy/feb_2026.strategy.ts ./content/feb_2026.strategy/feb_2026.test.ts
|
|
3511
3781
|
node ${ENTRY_PATH} --init --output my-trading-bot
|
|
@@ -3518,7 +3788,7 @@ const main$1 = async () => {
|
|
|
3518
3788
|
if (!values.help) {
|
|
3519
3789
|
return;
|
|
3520
3790
|
}
|
|
3521
|
-
process.stdout.write(`@backtest-kit/cli ${"7.
|
|
3791
|
+
process.stdout.write(`@backtest-kit/cli ${"7.5.0"}\n\n`);
|
|
3522
3792
|
process.stdout.write(HELP_TEXT);
|
|
3523
3793
|
process.exit(0);
|
|
3524
3794
|
};
|
|
@@ -3532,7 +3802,7 @@ const main = async () => {
|
|
|
3532
3802
|
if (!values.version) {
|
|
3533
3803
|
return;
|
|
3534
3804
|
}
|
|
3535
|
-
process.stdout.write(`@backtest-kit/cli ${"7.
|
|
3805
|
+
process.stdout.write(`@backtest-kit/cli ${"7.5.0"}\n`);
|
|
3536
3806
|
process.exit(0);
|
|
3537
3807
|
};
|
|
3538
3808
|
main();
|