@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.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import * as BacktestKit from 'backtest-kit';
|
|
3
|
-
import { setConfig, Log, listExchangeSchema, addExchangeSchema, roundTicks, listFrameSchema, addFrameSchema, listenDoneLive, listenDoneBacktest, shutdown, listenSignal, Notification, Recent, Storage, Markdown, Report, Dump, Memory, StorageLive, StorageBacktest, RecentLive, RecentBacktest, NotificationLive, NotificationBacktest, MarkdownWriter, ReportWriter, PersistSignalAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistPartialAdapter, PersistBreakevenAdapter, PersistCandleAdapter, PersistStorageAdapter, PersistNotificationAdapter, PersistLogAdapter, PersistMeasureAdapter, PersistIntervalAdapter, PersistMemoryAdapter, PersistRecentAdapter, listStrategySchema, overrideExchangeSchema, Backtest, Session, Cache, Interval, alignToInterval, addWalkerSchema, overrideWalkerSchema, Walker, listenDoneWalker, Live, getCandles, checkCandles, warmCandles, listenRisk, listenStrategyCommit, listenSync, listenSignalNotify, Exchange } from 'backtest-kit';
|
|
3
|
+
import { setConfig, Log, listExchangeSchema, addExchangeSchema, roundTicks, listFrameSchema, addFrameSchema, listenDoneLive, listenDoneBacktest, shutdown, listenSignal, Notification, Recent, Storage, Markdown, Report, Dump, State, Memory, StorageLive, StorageBacktest, RecentLive, RecentBacktest, NotificationLive, NotificationBacktest, MemoryLive, MemoryBacktest, StateLive, StateBacktest, MarkdownWriter, ReportWriter, PersistSignalAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistPartialAdapter, PersistBreakevenAdapter, PersistCandleAdapter, PersistStorageAdapter, PersistNotificationAdapter, PersistLogAdapter, PersistMeasureAdapter, PersistIntervalAdapter, PersistMemoryAdapter, PersistRecentAdapter, PersistStateAdapter, listStrategySchema, overrideExchangeSchema, Backtest, Session, Cache, Interval, alignToInterval, addWalkerSchema, overrideWalkerSchema, Walker, listenDoneWalker, Live, getCandles, checkCandles, warmCandles, listenRisk, listenStrategyCommit, listenSync, listenSignalNotify, Exchange } from 'backtest-kit';
|
|
4
4
|
import { getErrorMessage, errorData, singleshot, str, BehaviorSubject, compose, createAwaiter, execpool, queued, sleep, randomString, TIMEOUT_SYMBOL, typo, retry, trycatch, memoize, isObject } from 'functools-kit';
|
|
5
5
|
import fs, { constants } from 'fs';
|
|
6
6
|
import * as stackTrace from 'stack-trace';
|
|
@@ -545,6 +545,22 @@ const getArgs = singleshot(() => {
|
|
|
545
545
|
type: "boolean",
|
|
546
546
|
default: false,
|
|
547
547
|
},
|
|
548
|
+
pnldebug: {
|
|
549
|
+
type: "boolean",
|
|
550
|
+
default: false,
|
|
551
|
+
},
|
|
552
|
+
priceopen: {
|
|
553
|
+
type: "string",
|
|
554
|
+
default: "",
|
|
555
|
+
},
|
|
556
|
+
direction: {
|
|
557
|
+
type: "string",
|
|
558
|
+
default: "",
|
|
559
|
+
},
|
|
560
|
+
minutes: {
|
|
561
|
+
type: "string",
|
|
562
|
+
default: "",
|
|
563
|
+
},
|
|
548
564
|
init: {
|
|
549
565
|
type: "boolean",
|
|
550
566
|
default: false,
|
|
@@ -691,11 +707,11 @@ class SetupUtils {
|
|
|
691
707
|
Markdown.enable();
|
|
692
708
|
Report.enable();
|
|
693
709
|
Dump.enable();
|
|
710
|
+
State.enable();
|
|
694
711
|
Memory.enable();
|
|
695
712
|
}
|
|
696
713
|
{
|
|
697
714
|
Dump.useMarkdown();
|
|
698
|
-
Memory.usePersist();
|
|
699
715
|
}
|
|
700
716
|
{
|
|
701
717
|
StorageLive.usePersist();
|
|
@@ -709,6 +725,18 @@ class SetupUtils {
|
|
|
709
725
|
NotificationLive.usePersist();
|
|
710
726
|
NotificationBacktest.useMemory();
|
|
711
727
|
}
|
|
728
|
+
{
|
|
729
|
+
RecentLive.usePersist();
|
|
730
|
+
RecentBacktest.useMemory();
|
|
731
|
+
}
|
|
732
|
+
{
|
|
733
|
+
MemoryLive.usePersist();
|
|
734
|
+
MemoryBacktest.useLocal();
|
|
735
|
+
}
|
|
736
|
+
{
|
|
737
|
+
StateLive.usePersist();
|
|
738
|
+
StateBacktest.useLocal();
|
|
739
|
+
}
|
|
712
740
|
{
|
|
713
741
|
Markdown.useDummy();
|
|
714
742
|
Log.useJsonl();
|
|
@@ -751,6 +779,7 @@ class SetupUtils {
|
|
|
751
779
|
PersistIntervalAdapter.clear();
|
|
752
780
|
PersistMemoryAdapter.clear();
|
|
753
781
|
PersistRecentAdapter.clear();
|
|
782
|
+
PersistStateAdapter.clear();
|
|
754
783
|
}
|
|
755
784
|
{
|
|
756
785
|
Dump.clear();
|
|
@@ -1904,6 +1933,9 @@ class TelegramLogicService {
|
|
|
1904
1933
|
event,
|
|
1905
1934
|
});
|
|
1906
1935
|
const markdown = await this.telegramTemplateService.getTrailingTakeMarkdown(event);
|
|
1936
|
+
if (!markdown) {
|
|
1937
|
+
return;
|
|
1938
|
+
}
|
|
1907
1939
|
await this.telegramWebService.publishNotify({
|
|
1908
1940
|
symbol: event.symbol,
|
|
1909
1941
|
markdown,
|
|
@@ -1914,6 +1946,9 @@ class TelegramLogicService {
|
|
|
1914
1946
|
event,
|
|
1915
1947
|
});
|
|
1916
1948
|
const markdown = await this.telegramTemplateService.getTrailingStopMarkdown(event);
|
|
1949
|
+
if (!markdown) {
|
|
1950
|
+
return;
|
|
1951
|
+
}
|
|
1917
1952
|
await this.telegramWebService.publishNotify({
|
|
1918
1953
|
symbol: event.symbol,
|
|
1919
1954
|
markdown,
|
|
@@ -1924,6 +1959,9 @@ class TelegramLogicService {
|
|
|
1924
1959
|
event,
|
|
1925
1960
|
});
|
|
1926
1961
|
const markdown = await this.telegramTemplateService.getBreakevenMarkdown(event);
|
|
1962
|
+
if (!markdown) {
|
|
1963
|
+
return;
|
|
1964
|
+
}
|
|
1927
1965
|
await this.telegramWebService.publishNotify({
|
|
1928
1966
|
symbol: event.symbol,
|
|
1929
1967
|
markdown,
|
|
@@ -1934,6 +1972,9 @@ class TelegramLogicService {
|
|
|
1934
1972
|
event,
|
|
1935
1973
|
});
|
|
1936
1974
|
const markdown = await this.telegramTemplateService.getPartialProfitMarkdown(event);
|
|
1975
|
+
if (!markdown) {
|
|
1976
|
+
return;
|
|
1977
|
+
}
|
|
1937
1978
|
await this.telegramWebService.publishNotify({
|
|
1938
1979
|
symbol: event.symbol,
|
|
1939
1980
|
markdown,
|
|
@@ -1944,6 +1985,9 @@ class TelegramLogicService {
|
|
|
1944
1985
|
event,
|
|
1945
1986
|
});
|
|
1946
1987
|
const markdown = await this.telegramTemplateService.getPartialLossMarkdown(event);
|
|
1988
|
+
if (!markdown) {
|
|
1989
|
+
return;
|
|
1990
|
+
}
|
|
1947
1991
|
await this.telegramWebService.publishNotify({
|
|
1948
1992
|
symbol: event.symbol,
|
|
1949
1993
|
markdown,
|
|
@@ -1954,6 +1998,9 @@ class TelegramLogicService {
|
|
|
1954
1998
|
event,
|
|
1955
1999
|
});
|
|
1956
2000
|
const markdown = await this.telegramTemplateService.getScheduledMarkdown(event);
|
|
2001
|
+
if (!markdown) {
|
|
2002
|
+
return;
|
|
2003
|
+
}
|
|
1957
2004
|
await this.telegramWebService.publishNotify({
|
|
1958
2005
|
symbol: event.symbol,
|
|
1959
2006
|
markdown,
|
|
@@ -1964,6 +2011,9 @@ class TelegramLogicService {
|
|
|
1964
2011
|
event,
|
|
1965
2012
|
});
|
|
1966
2013
|
const markdown = await this.telegramTemplateService.getCancelledMarkdown(event);
|
|
2014
|
+
if (!markdown) {
|
|
2015
|
+
return;
|
|
2016
|
+
}
|
|
1967
2017
|
await this.telegramWebService.publishNotify({
|
|
1968
2018
|
symbol: event.symbol,
|
|
1969
2019
|
markdown,
|
|
@@ -1974,6 +2024,9 @@ class TelegramLogicService {
|
|
|
1974
2024
|
event,
|
|
1975
2025
|
});
|
|
1976
2026
|
const markdown = await this.telegramTemplateService.getOpenedMarkdown(event);
|
|
2027
|
+
if (!markdown) {
|
|
2028
|
+
return;
|
|
2029
|
+
}
|
|
1977
2030
|
await this.telegramWebService.publishNotify({
|
|
1978
2031
|
symbol: event.symbol,
|
|
1979
2032
|
markdown,
|
|
@@ -1984,6 +2037,9 @@ class TelegramLogicService {
|
|
|
1984
2037
|
event,
|
|
1985
2038
|
});
|
|
1986
2039
|
const markdown = await this.telegramTemplateService.getClosedMarkdown(event);
|
|
2040
|
+
if (!markdown) {
|
|
2041
|
+
return;
|
|
2042
|
+
}
|
|
1987
2043
|
await this.telegramWebService.publishNotify({
|
|
1988
2044
|
symbol: event.symbol,
|
|
1989
2045
|
markdown,
|
|
@@ -1994,6 +2050,9 @@ class TelegramLogicService {
|
|
|
1994
2050
|
event,
|
|
1995
2051
|
});
|
|
1996
2052
|
const markdown = await this.telegramTemplateService.getRiskMarkdown(event);
|
|
2053
|
+
if (!markdown) {
|
|
2054
|
+
return;
|
|
2055
|
+
}
|
|
1997
2056
|
await this.telegramWebService.publishNotify({
|
|
1998
2057
|
symbol: event.symbol,
|
|
1999
2058
|
markdown,
|
|
@@ -2004,6 +2063,9 @@ class TelegramLogicService {
|
|
|
2004
2063
|
event,
|
|
2005
2064
|
});
|
|
2006
2065
|
const markdown = await this.telegramTemplateService.getAverageBuyMarkdown(event);
|
|
2066
|
+
if (!markdown) {
|
|
2067
|
+
return;
|
|
2068
|
+
}
|
|
2007
2069
|
await this.telegramWebService.publishNotify({
|
|
2008
2070
|
symbol: event.symbol,
|
|
2009
2071
|
markdown,
|
|
@@ -2014,6 +2076,9 @@ class TelegramLogicService {
|
|
|
2014
2076
|
event,
|
|
2015
2077
|
});
|
|
2016
2078
|
const markdown = await this.telegramTemplateService.getSignalOpenMarkdown(event);
|
|
2079
|
+
if (!markdown) {
|
|
2080
|
+
return;
|
|
2081
|
+
}
|
|
2017
2082
|
await this.telegramWebService.publishNotify({
|
|
2018
2083
|
symbol: event.symbol,
|
|
2019
2084
|
markdown,
|
|
@@ -2024,6 +2089,9 @@ class TelegramLogicService {
|
|
|
2024
2089
|
event,
|
|
2025
2090
|
});
|
|
2026
2091
|
const markdown = await this.telegramTemplateService.getSignalCloseMarkdown(event);
|
|
2092
|
+
if (!markdown) {
|
|
2093
|
+
return;
|
|
2094
|
+
}
|
|
2027
2095
|
await this.telegramWebService.publishNotify({
|
|
2028
2096
|
symbol: event.symbol,
|
|
2029
2097
|
markdown,
|
|
@@ -2034,6 +2102,9 @@ class TelegramLogicService {
|
|
|
2034
2102
|
event,
|
|
2035
2103
|
});
|
|
2036
2104
|
const markdown = await this.telegramTemplateService.getSignalInfoMarkdown(event);
|
|
2105
|
+
if (!markdown) {
|
|
2106
|
+
return;
|
|
2107
|
+
}
|
|
2037
2108
|
await this.telegramWebService.publishNotify({
|
|
2038
2109
|
symbol: event.symbol,
|
|
2039
2110
|
markdown,
|
|
@@ -2044,6 +2115,9 @@ class TelegramLogicService {
|
|
|
2044
2115
|
event,
|
|
2045
2116
|
});
|
|
2046
2117
|
const markdown = await this.telegramTemplateService.getCancelScheduledMarkdown(event);
|
|
2118
|
+
if (!markdown) {
|
|
2119
|
+
return;
|
|
2120
|
+
}
|
|
2047
2121
|
await this.telegramWebService.publishNotify({
|
|
2048
2122
|
symbol: event.symbol,
|
|
2049
2123
|
markdown,
|
|
@@ -2054,6 +2128,9 @@ class TelegramLogicService {
|
|
|
2054
2128
|
event,
|
|
2055
2129
|
});
|
|
2056
2130
|
const markdown = await this.telegramTemplateService.getClosePendingMarkdown(event);
|
|
2131
|
+
if (!markdown) {
|
|
2132
|
+
return;
|
|
2133
|
+
}
|
|
2057
2134
|
await this.telegramWebService.publishNotify({
|
|
2058
2135
|
symbol: event.symbol,
|
|
2059
2136
|
markdown,
|
|
@@ -2155,104 +2232,182 @@ const RENDER_TEMPLATE_FN = async (fileName, event, self) => {
|
|
|
2155
2232
|
const template = await READ_TEMPLATE_FN(fileName, self);
|
|
2156
2233
|
return Mustache.render(template, event);
|
|
2157
2234
|
};
|
|
2235
|
+
const GET_TELEGRAM_CONFIG_FN = async (self) => {
|
|
2236
|
+
const exports = await self.configConnectionService.loadConfig("telegram.config");
|
|
2237
|
+
if (!exports) {
|
|
2238
|
+
return null;
|
|
2239
|
+
}
|
|
2240
|
+
return "default" in exports
|
|
2241
|
+
? exports.default
|
|
2242
|
+
: exports;
|
|
2243
|
+
};
|
|
2158
2244
|
class TelegramTemplateService {
|
|
2159
2245
|
constructor() {
|
|
2160
2246
|
this.loggerService = inject(TYPES.loggerService);
|
|
2161
2247
|
this.resolveService = inject(TYPES.resolveService);
|
|
2248
|
+
this.configConnectionService = inject(TYPES.configConnectionService);
|
|
2249
|
+
this.getTelegramAdapter = singleshot(async () => {
|
|
2250
|
+
this.loggerService.log("telegramTemplateService getTelegramAdapter");
|
|
2251
|
+
return await GET_TELEGRAM_CONFIG_FN(this);
|
|
2252
|
+
});
|
|
2162
2253
|
this.getTrailingTakeMarkdown = async (event) => {
|
|
2163
2254
|
this.loggerService.log("telegramTemplateService getTrailingTakeMarkdown", {
|
|
2164
2255
|
event,
|
|
2165
2256
|
});
|
|
2257
|
+
const adapter = await this.getTelegramAdapter();
|
|
2258
|
+
if (adapter?.getTrailingTakeMarkdown) {
|
|
2259
|
+
return await adapter.getTrailingTakeMarkdown(event);
|
|
2260
|
+
}
|
|
2166
2261
|
return await RENDER_TEMPLATE_FN("trailing-take.mustache", event, this);
|
|
2167
2262
|
};
|
|
2168
2263
|
this.getTrailingStopMarkdown = async (event) => {
|
|
2169
2264
|
this.loggerService.log("telegramTemplateService getTrailingStopMarkdown", {
|
|
2170
2265
|
event,
|
|
2171
2266
|
});
|
|
2267
|
+
const adapter = await this.getTelegramAdapter();
|
|
2268
|
+
if (adapter?.getTrailingStopMarkdown) {
|
|
2269
|
+
return await adapter.getTrailingStopMarkdown(event);
|
|
2270
|
+
}
|
|
2172
2271
|
return await RENDER_TEMPLATE_FN("trailing-stop.mustache", event, this);
|
|
2173
2272
|
};
|
|
2174
2273
|
this.getBreakevenMarkdown = async (event) => {
|
|
2175
2274
|
this.loggerService.log("telegramTemplateService getBreakevenMarkdown", {
|
|
2176
2275
|
event,
|
|
2177
2276
|
});
|
|
2277
|
+
const adapter = await this.getTelegramAdapter();
|
|
2278
|
+
if (adapter?.getBreakevenMarkdown) {
|
|
2279
|
+
return await adapter.getBreakevenMarkdown(event);
|
|
2280
|
+
}
|
|
2178
2281
|
return await RENDER_TEMPLATE_FN("breakeven.mustache", event, this);
|
|
2179
2282
|
};
|
|
2180
2283
|
this.getPartialProfitMarkdown = async (event) => {
|
|
2181
2284
|
this.loggerService.log("telegramTemplateService getPartialProfitMarkdown", {
|
|
2182
2285
|
event,
|
|
2183
2286
|
});
|
|
2287
|
+
const adapter = await this.getTelegramAdapter();
|
|
2288
|
+
if (adapter?.getPartialProfitMarkdown) {
|
|
2289
|
+
return await adapter.getPartialProfitMarkdown(event);
|
|
2290
|
+
}
|
|
2184
2291
|
return await RENDER_TEMPLATE_FN("partial-profit.mustache", event, this);
|
|
2185
2292
|
};
|
|
2186
2293
|
this.getPartialLossMarkdown = async (event) => {
|
|
2187
2294
|
this.loggerService.log("telegramTemplateService getPartialLossMarkdown", {
|
|
2188
2295
|
event,
|
|
2189
2296
|
});
|
|
2297
|
+
const adapter = await this.getTelegramAdapter();
|
|
2298
|
+
if (adapter?.getPartialLossMarkdown) {
|
|
2299
|
+
return await adapter.getPartialLossMarkdown(event);
|
|
2300
|
+
}
|
|
2190
2301
|
return await RENDER_TEMPLATE_FN("partial-loss.mustache", event, this);
|
|
2191
2302
|
};
|
|
2192
2303
|
this.getScheduledMarkdown = async (event) => {
|
|
2193
2304
|
this.loggerService.log("telegramTemplateService getScheduledMarkdown", {
|
|
2194
2305
|
event,
|
|
2195
2306
|
});
|
|
2307
|
+
const adapter = await this.getTelegramAdapter();
|
|
2308
|
+
if (adapter?.getScheduledMarkdown) {
|
|
2309
|
+
return await adapter.getScheduledMarkdown(event);
|
|
2310
|
+
}
|
|
2196
2311
|
return await RENDER_TEMPLATE_FN("scheduled.mustache", event, this);
|
|
2197
2312
|
};
|
|
2198
2313
|
this.getCancelledMarkdown = async (event) => {
|
|
2199
2314
|
this.loggerService.log("telegramTemplateService getCancelledMarkdown", {
|
|
2200
2315
|
event,
|
|
2201
2316
|
});
|
|
2317
|
+
const adapter = await this.getTelegramAdapter();
|
|
2318
|
+
if (adapter?.getCancelledMarkdown) {
|
|
2319
|
+
return await adapter.getCancelledMarkdown(event);
|
|
2320
|
+
}
|
|
2202
2321
|
return await RENDER_TEMPLATE_FN("cancelled.mustache", event, this);
|
|
2203
2322
|
};
|
|
2204
2323
|
this.getOpenedMarkdown = async (event) => {
|
|
2205
2324
|
this.loggerService.log("telegramTemplateService getOpenedMarkdown", {
|
|
2206
2325
|
event,
|
|
2207
2326
|
});
|
|
2327
|
+
const adapter = await this.getTelegramAdapter();
|
|
2328
|
+
if (adapter?.getOpenedMarkdown) {
|
|
2329
|
+
return await adapter.getOpenedMarkdown(event);
|
|
2330
|
+
}
|
|
2208
2331
|
return await RENDER_TEMPLATE_FN("opened.mustache", event, this);
|
|
2209
2332
|
};
|
|
2210
2333
|
this.getClosedMarkdown = async (event) => {
|
|
2211
2334
|
this.loggerService.log("telegramTemplateService getClosedMarkdown", {
|
|
2212
2335
|
event,
|
|
2213
2336
|
});
|
|
2337
|
+
const adapter = await this.getTelegramAdapter();
|
|
2338
|
+
if (adapter?.getClosedMarkdown) {
|
|
2339
|
+
return await adapter.getClosedMarkdown(event);
|
|
2340
|
+
}
|
|
2214
2341
|
return await RENDER_TEMPLATE_FN("closed.mustache", event, this);
|
|
2215
2342
|
};
|
|
2216
2343
|
this.getRiskMarkdown = async (event) => {
|
|
2217
2344
|
this.loggerService.log("telegramTemplateService getRiskMarkdown", {
|
|
2218
2345
|
event,
|
|
2219
2346
|
});
|
|
2347
|
+
const adapter = await this.getTelegramAdapter();
|
|
2348
|
+
if (adapter?.getRiskMarkdown) {
|
|
2349
|
+
return await adapter.getRiskMarkdown(event);
|
|
2350
|
+
}
|
|
2220
2351
|
return await RENDER_TEMPLATE_FN("risk.mustache", event, this);
|
|
2221
2352
|
};
|
|
2222
2353
|
this.getAverageBuyMarkdown = async (event) => {
|
|
2223
2354
|
this.loggerService.log("telegramTemplateService getAverageBuyMarkdown", {
|
|
2224
2355
|
event,
|
|
2225
2356
|
});
|
|
2357
|
+
const adapter = await this.getTelegramAdapter();
|
|
2358
|
+
if (adapter?.getAverageBuyMarkdown) {
|
|
2359
|
+
return await adapter.getAverageBuyMarkdown(event);
|
|
2360
|
+
}
|
|
2226
2361
|
return await RENDER_TEMPLATE_FN("average-buy.mustache", event, this);
|
|
2227
2362
|
};
|
|
2228
2363
|
this.getSignalOpenMarkdown = async (event) => {
|
|
2229
2364
|
this.loggerService.log("telegramTemplateService getSignalOpenMarkdown", {
|
|
2230
2365
|
event,
|
|
2231
2366
|
});
|
|
2367
|
+
const adapter = await this.getTelegramAdapter();
|
|
2368
|
+
if (adapter?.getSignalOpenMarkdown) {
|
|
2369
|
+
return await adapter.getSignalOpenMarkdown(event);
|
|
2370
|
+
}
|
|
2232
2371
|
return await RENDER_TEMPLATE_FN("signal-open.mustache", event, this);
|
|
2233
2372
|
};
|
|
2234
2373
|
this.getSignalCloseMarkdown = async (event) => {
|
|
2235
2374
|
this.loggerService.log("telegramTemplateService getSignalCloseMarkdown", {
|
|
2236
2375
|
event,
|
|
2237
2376
|
});
|
|
2377
|
+
const adapter = await this.getTelegramAdapter();
|
|
2378
|
+
if (adapter?.getSignalCloseMarkdown) {
|
|
2379
|
+
return await adapter.getSignalCloseMarkdown(event);
|
|
2380
|
+
}
|
|
2238
2381
|
return await RENDER_TEMPLATE_FN("signal-close.mustache", event, this);
|
|
2239
2382
|
};
|
|
2240
2383
|
this.getCancelScheduledMarkdown = async (event) => {
|
|
2241
2384
|
this.loggerService.log("telegramTemplateService getCancelScheduledMarkdown", {
|
|
2242
2385
|
event,
|
|
2243
2386
|
});
|
|
2387
|
+
const adapter = await this.getTelegramAdapter();
|
|
2388
|
+
if (adapter?.getCancelScheduledMarkdown) {
|
|
2389
|
+
return await adapter.getCancelScheduledMarkdown(event);
|
|
2390
|
+
}
|
|
2244
2391
|
return await RENDER_TEMPLATE_FN("cancel-scheduled.mustache", event, this);
|
|
2245
2392
|
};
|
|
2246
2393
|
this.getClosePendingMarkdown = async (event) => {
|
|
2247
2394
|
this.loggerService.log("telegramTemplateService getClosePendingMarkdown", {
|
|
2248
2395
|
event,
|
|
2249
2396
|
});
|
|
2397
|
+
const adapter = await this.getTelegramAdapter();
|
|
2398
|
+
if (adapter?.getClosePendingMarkdown) {
|
|
2399
|
+
return await adapter.getClosePendingMarkdown(event);
|
|
2400
|
+
}
|
|
2250
2401
|
return await RENDER_TEMPLATE_FN("close-pending.mustache", event, this);
|
|
2251
2402
|
};
|
|
2252
2403
|
this.getSignalInfoMarkdown = async (event) => {
|
|
2253
2404
|
this.loggerService.log("telegramTemplateService getSignalInfoMarkdown", {
|
|
2254
2405
|
event,
|
|
2255
2406
|
});
|
|
2407
|
+
const adapter = await this.getTelegramAdapter();
|
|
2408
|
+
if (adapter?.getSignalInfoMarkdown) {
|
|
2409
|
+
return await adapter.getSignalInfoMarkdown(event);
|
|
2410
|
+
}
|
|
2256
2411
|
return await RENDER_TEMPLATE_FN("signal-info.mustache", event, this);
|
|
2257
2412
|
};
|
|
2258
2413
|
}
|
|
@@ -2810,14 +2965,14 @@ const cli = {
|
|
|
2810
2965
|
};
|
|
2811
2966
|
init();
|
|
2812
2967
|
|
|
2813
|
-
const MODES = ["backtest", "walker", "paper", "live", "pine", "editor", "dump", "flush", "init", "help", "version"];
|
|
2968
|
+
const MODES = ["backtest", "walker", "paper", "live", "pine", "editor", "dump", "pnldebug", "flush", "init", "help", "version"];
|
|
2814
2969
|
const ENTRY_PATH$1 = "./node_modules/@backtest-kit/cli/build/index.mjs";
|
|
2815
2970
|
const HELP_TEXT$1 = `
|
|
2816
2971
|
Example:
|
|
2817
2972
|
|
|
2818
2973
|
node ${ENTRY_PATH$1} --help
|
|
2819
2974
|
`.trimStart();
|
|
2820
|
-
const main$
|
|
2975
|
+
const main$e = async () => {
|
|
2821
2976
|
if (!getEntry(import.meta.url)) {
|
|
2822
2977
|
return;
|
|
2823
2978
|
}
|
|
@@ -2825,14 +2980,14 @@ const main$d = async () => {
|
|
|
2825
2980
|
if (MODES.some((mode) => values[mode])) {
|
|
2826
2981
|
return;
|
|
2827
2982
|
}
|
|
2828
|
-
process.stdout.write(`@backtest-kit/cli ${"7.
|
|
2983
|
+
process.stdout.write(`@backtest-kit/cli ${"7.5.0"}\n`);
|
|
2829
2984
|
process.stdout.write("\n");
|
|
2830
2985
|
process.stdout.write(`Run with --help to see available commands.\n`);
|
|
2831
2986
|
process.stdout.write("\n");
|
|
2832
2987
|
process.stdout.write(HELP_TEXT$1);
|
|
2833
2988
|
process.exit(0);
|
|
2834
2989
|
};
|
|
2835
|
-
main$
|
|
2990
|
+
main$e();
|
|
2836
2991
|
|
|
2837
2992
|
const notifyShutdown = singleshot(async () => {
|
|
2838
2993
|
console.log("Graceful shutdown initiated. Press Ctrl+C again to force quit.");
|
|
@@ -2848,7 +3003,7 @@ const flush = async (entryPoint) => {
|
|
|
2848
3003
|
console.log(`Removed: ${target}`);
|
|
2849
3004
|
}
|
|
2850
3005
|
};
|
|
2851
|
-
const main$
|
|
3006
|
+
const main$d = async () => {
|
|
2852
3007
|
if (!getEntry(import.meta.url)) {
|
|
2853
3008
|
return;
|
|
2854
3009
|
}
|
|
@@ -2865,7 +3020,7 @@ const main$c = async () => {
|
|
|
2865
3020
|
}
|
|
2866
3021
|
process.exit(0);
|
|
2867
3022
|
};
|
|
2868
|
-
main$
|
|
3023
|
+
main$d();
|
|
2869
3024
|
|
|
2870
3025
|
const BEFORE_EXIT_FN$5 = singleshot(async () => {
|
|
2871
3026
|
process.off("SIGINT", BEFORE_EXIT_FN$5);
|
|
@@ -2887,7 +3042,7 @@ const BEFORE_EXIT_FN$5 = singleshot(async () => {
|
|
|
2887
3042
|
const listenGracefulShutdown$5 = singleshot(() => {
|
|
2888
3043
|
process.on("SIGINT", BEFORE_EXIT_FN$5);
|
|
2889
3044
|
});
|
|
2890
|
-
const main$
|
|
3045
|
+
const main$c = async () => {
|
|
2891
3046
|
if (!getEntry(import.meta.url)) {
|
|
2892
3047
|
return;
|
|
2893
3048
|
}
|
|
@@ -2902,7 +3057,7 @@ const main$b = async () => {
|
|
|
2902
3057
|
await cli.backtestMainService.connect();
|
|
2903
3058
|
listenGracefulShutdown$5();
|
|
2904
3059
|
};
|
|
2905
|
-
main$
|
|
3060
|
+
main$c();
|
|
2906
3061
|
|
|
2907
3062
|
const BEFORE_EXIT_FN$4 = singleshot(async () => {
|
|
2908
3063
|
process.off("SIGINT", BEFORE_EXIT_FN$4);
|
|
@@ -2920,7 +3075,7 @@ const BEFORE_EXIT_FN$4 = singleshot(async () => {
|
|
|
2920
3075
|
const listenGracefulShutdown$4 = singleshot(() => {
|
|
2921
3076
|
process.on("SIGINT", BEFORE_EXIT_FN$4);
|
|
2922
3077
|
});
|
|
2923
|
-
const main$
|
|
3078
|
+
const main$b = async () => {
|
|
2924
3079
|
if (!getEntry(import.meta.url)) {
|
|
2925
3080
|
return;
|
|
2926
3081
|
}
|
|
@@ -2936,7 +3091,7 @@ const main$a = async () => {
|
|
|
2936
3091
|
listenGracefulShutdown$4();
|
|
2937
3092
|
await cli.walkerMainService.connect();
|
|
2938
3093
|
};
|
|
2939
|
-
main$
|
|
3094
|
+
main$b();
|
|
2940
3095
|
|
|
2941
3096
|
const BEFORE_EXIT_FN$3 = singleshot(async () => {
|
|
2942
3097
|
process.off("SIGINT", BEFORE_EXIT_FN$3);
|
|
@@ -2957,7 +3112,7 @@ const BEFORE_EXIT_FN$3 = singleshot(async () => {
|
|
|
2957
3112
|
const listenGracefulShutdown$3 = singleshot(() => {
|
|
2958
3113
|
process.on("SIGINT", BEFORE_EXIT_FN$3);
|
|
2959
3114
|
});
|
|
2960
|
-
const main$
|
|
3115
|
+
const main$a = async () => {
|
|
2961
3116
|
if (!getEntry(import.meta.url)) {
|
|
2962
3117
|
return;
|
|
2963
3118
|
}
|
|
@@ -2968,7 +3123,7 @@ const main$9 = async () => {
|
|
|
2968
3123
|
cli.paperMainService.connect();
|
|
2969
3124
|
listenGracefulShutdown$3();
|
|
2970
3125
|
};
|
|
2971
|
-
main$
|
|
3126
|
+
main$a();
|
|
2972
3127
|
|
|
2973
3128
|
const BEFORE_EXIT_FN$2 = singleshot(async () => {
|
|
2974
3129
|
process.off("SIGINT", BEFORE_EXIT_FN$2);
|
|
@@ -2989,7 +3144,7 @@ const BEFORE_EXIT_FN$2 = singleshot(async () => {
|
|
|
2989
3144
|
const listenGracefulShutdown$2 = singleshot(() => {
|
|
2990
3145
|
process.on("SIGINT", BEFORE_EXIT_FN$2);
|
|
2991
3146
|
});
|
|
2992
|
-
const main$
|
|
3147
|
+
const main$9 = async () => {
|
|
2993
3148
|
if (!getEntry(import.meta.url)) {
|
|
2994
3149
|
return;
|
|
2995
3150
|
}
|
|
@@ -3000,7 +3155,7 @@ const main$8 = async () => {
|
|
|
3000
3155
|
await cli.liveMainService.connect();
|
|
3001
3156
|
listenGracefulShutdown$2();
|
|
3002
3157
|
};
|
|
3003
|
-
main$
|
|
3158
|
+
main$9();
|
|
3004
3159
|
|
|
3005
3160
|
const BEFORE_EXIT_FN$1 = singleshot(async () => {
|
|
3006
3161
|
process.off("SIGINT", BEFORE_EXIT_FN$1);
|
|
@@ -3010,7 +3165,7 @@ const BEFORE_EXIT_FN$1 = singleshot(async () => {
|
|
|
3010
3165
|
const listenGracefulShutdown$1 = singleshot(() => {
|
|
3011
3166
|
process.on("SIGINT", BEFORE_EXIT_FN$1);
|
|
3012
3167
|
});
|
|
3013
|
-
const main$
|
|
3168
|
+
const main$8 = async () => {
|
|
3014
3169
|
if (!getEntry(import.meta.url)) {
|
|
3015
3170
|
return;
|
|
3016
3171
|
}
|
|
@@ -3020,7 +3175,7 @@ const main$7 = async () => {
|
|
|
3020
3175
|
}
|
|
3021
3176
|
listenGracefulShutdown$1();
|
|
3022
3177
|
};
|
|
3023
|
-
main$
|
|
3178
|
+
main$8();
|
|
3024
3179
|
|
|
3025
3180
|
const BEFORE_EXIT_FN = singleshot(async () => {
|
|
3026
3181
|
process.off("SIGINT", BEFORE_EXIT_FN);
|
|
@@ -3030,7 +3185,7 @@ const BEFORE_EXIT_FN = singleshot(async () => {
|
|
|
3030
3185
|
const listenGracefulShutdown = singleshot(() => {
|
|
3031
3186
|
process.on("SIGINT", BEFORE_EXIT_FN);
|
|
3032
3187
|
});
|
|
3033
|
-
const main$
|
|
3188
|
+
const main$7 = async () => {
|
|
3034
3189
|
if (!getEntry(import.meta.url)) {
|
|
3035
3190
|
return;
|
|
3036
3191
|
}
|
|
@@ -3040,7 +3195,7 @@ const main$6 = async () => {
|
|
|
3040
3195
|
}
|
|
3041
3196
|
listenGracefulShutdown();
|
|
3042
3197
|
};
|
|
3043
|
-
main$
|
|
3198
|
+
main$7();
|
|
3044
3199
|
|
|
3045
3200
|
const EXTRACT_ROWS_FN = (plots, schema) => {
|
|
3046
3201
|
const keys = Object.keys(schema);
|
|
@@ -3062,7 +3217,7 @@ const EXTRACT_ROWS_FN = (plots, schema) => {
|
|
|
3062
3217
|
}
|
|
3063
3218
|
return rows;
|
|
3064
3219
|
};
|
|
3065
|
-
const main$
|
|
3220
|
+
const main$6 = async () => {
|
|
3066
3221
|
if (!getEntry(import.meta.url)) {
|
|
3067
3222
|
return;
|
|
3068
3223
|
}
|
|
@@ -3142,9 +3297,9 @@ const main$5 = async () => {
|
|
|
3142
3297
|
console.log(await toMarkdown(signalId, plots, signalSchema));
|
|
3143
3298
|
process.exit(0);
|
|
3144
3299
|
};
|
|
3145
|
-
main$
|
|
3300
|
+
main$6();
|
|
3146
3301
|
|
|
3147
|
-
const main$
|
|
3302
|
+
const main$5 = async () => {
|
|
3148
3303
|
if (!getEntry(import.meta.url)) {
|
|
3149
3304
|
return;
|
|
3150
3305
|
}
|
|
@@ -3179,9 +3334,9 @@ const main$4 = async () => {
|
|
|
3179
3334
|
};
|
|
3180
3335
|
process.on("SIGINT", beforeExit);
|
|
3181
3336
|
};
|
|
3182
|
-
main$
|
|
3337
|
+
main$5();
|
|
3183
3338
|
|
|
3184
|
-
const main$
|
|
3339
|
+
const main$4 = async () => {
|
|
3185
3340
|
if (!getEntry(import.meta.url)) {
|
|
3186
3341
|
return;
|
|
3187
3342
|
}
|
|
@@ -3242,6 +3397,102 @@ const main$3 = async () => {
|
|
|
3242
3397
|
console.log(JSON.stringify(candles, null, 2));
|
|
3243
3398
|
process.exit(0);
|
|
3244
3399
|
};
|
|
3400
|
+
main$4();
|
|
3401
|
+
|
|
3402
|
+
const main$3 = async () => {
|
|
3403
|
+
if (!getEntry(import.meta.url)) {
|
|
3404
|
+
return;
|
|
3405
|
+
}
|
|
3406
|
+
const { values } = getArgs();
|
|
3407
|
+
if (!values.pnldebug) {
|
|
3408
|
+
return;
|
|
3409
|
+
}
|
|
3410
|
+
await cli.moduleConnectionService.loadModule("./pnldebug.module");
|
|
3411
|
+
{
|
|
3412
|
+
await cli.exchangeSchemaService.addSchema();
|
|
3413
|
+
await cli.symbolSchemaService.addSchema();
|
|
3414
|
+
}
|
|
3415
|
+
const [defaultExchangeName = null] = await listExchangeSchema();
|
|
3416
|
+
const exchangeName = values.exchange || defaultExchangeName?.exchangeName;
|
|
3417
|
+
const symbol = values.symbol || "BTCUSDT";
|
|
3418
|
+
const priceOpenStr = values.priceopen;
|
|
3419
|
+
if (!priceOpenStr) {
|
|
3420
|
+
console.error("Error: --priceopen is required");
|
|
3421
|
+
process.exit(1);
|
|
3422
|
+
}
|
|
3423
|
+
const priceOpen = parseFloat(priceOpenStr);
|
|
3424
|
+
if (isNaN(priceOpen)) {
|
|
3425
|
+
console.error(`Error: --priceopen must be a number, got: ${priceOpenStr}`);
|
|
3426
|
+
process.exit(1);
|
|
3427
|
+
}
|
|
3428
|
+
const direction = (values.direction || "long").toLowerCase();
|
|
3429
|
+
if (direction !== "long" && direction !== "short") {
|
|
3430
|
+
console.error(`Error: --direction must be 'long' or 'short', got: ${direction}`);
|
|
3431
|
+
process.exit(1);
|
|
3432
|
+
}
|
|
3433
|
+
const whenStr = values.when || Date.now().toString();
|
|
3434
|
+
const whenStamp = Date.parse(whenStr);
|
|
3435
|
+
const when = isNaN(whenStamp) ? new Date() : new Date(whenStamp);
|
|
3436
|
+
const timestamp = alignToInterval(when, "1m").getTime();
|
|
3437
|
+
const minutesStr = values.minutes || "60";
|
|
3438
|
+
const minutesNum = parseInt(minutesStr);
|
|
3439
|
+
const minutes = isNaN(minutesNum) ? 60 : minutesNum;
|
|
3440
|
+
const candles = await Exchange.getRawCandles(symbol, "1m", { exchangeName }, minutes, undefined, timestamp);
|
|
3441
|
+
if (candles.length === 0) {
|
|
3442
|
+
console.error("Error: no candles returned for the given parameters");
|
|
3443
|
+
process.exit(1);
|
|
3444
|
+
}
|
|
3445
|
+
let peak = 0;
|
|
3446
|
+
let drawdown = 0;
|
|
3447
|
+
const rows = candles.map((c, i) => {
|
|
3448
|
+
const pnl = direction === "short"
|
|
3449
|
+
? (priceOpen - c.close) / priceOpen * 100
|
|
3450
|
+
: (c.close - priceOpen) / priceOpen * 100;
|
|
3451
|
+
if (pnl > peak)
|
|
3452
|
+
peak = pnl;
|
|
3453
|
+
if (pnl < drawdown)
|
|
3454
|
+
drawdown = pnl;
|
|
3455
|
+
return { min: i + 1, timestamp: c.timestamp, close: c.close, pnl, peak, drawdown };
|
|
3456
|
+
});
|
|
3457
|
+
const dumpName = values.output || `${symbol}_${direction}_${priceOpen}_${timestamp}`;
|
|
3458
|
+
const dumpDir = join(process.cwd(), "dump");
|
|
3459
|
+
if (values.json) {
|
|
3460
|
+
const filePath = resolve(dumpDir, `${dumpName}.json`);
|
|
3461
|
+
await mkdir(dumpDir, { recursive: true });
|
|
3462
|
+
await writeFile(filePath, JSON.stringify(rows, null, 2), "utf-8");
|
|
3463
|
+
console.log(`Saved: ${filePath}`);
|
|
3464
|
+
process.exit(0);
|
|
3465
|
+
}
|
|
3466
|
+
if (values.jsonl) {
|
|
3467
|
+
const filePath = resolve(dumpDir, `${dumpName}.jsonl`);
|
|
3468
|
+
await mkdir(dumpDir, { recursive: true });
|
|
3469
|
+
await writeFile(filePath, rows.map((r) => JSON.stringify(r)).join("\n"), "utf-8");
|
|
3470
|
+
console.log(`Saved: ${filePath}`);
|
|
3471
|
+
process.exit(0);
|
|
3472
|
+
}
|
|
3473
|
+
if (values.markdown) {
|
|
3474
|
+
const header = `| min | timestamp | close | pnl% | peak% | drawdown% |\n| --- | --- | --- | --- | --- | --- |`;
|
|
3475
|
+
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)}% |`);
|
|
3476
|
+
const filePath = resolve(dumpDir, `${dumpName}.md`);
|
|
3477
|
+
await mkdir(dumpDir, { recursive: true });
|
|
3478
|
+
await writeFile(filePath, [header, ...mdRows].join("\n"), "utf-8");
|
|
3479
|
+
console.log(`Saved: ${filePath}`);
|
|
3480
|
+
process.exit(0);
|
|
3481
|
+
}
|
|
3482
|
+
console.log(`Symbol: ${symbol} | Direction: ${direction} | PriceOpen: ${priceOpen} | From: ${new Date(timestamp).toISOString()} | Minutes: ${minutes}\n`);
|
|
3483
|
+
console.log(`${"min".padStart(5)} | ${"timestamp".padEnd(24)} | ${"close".padStart(12)} | ${"pnl%".padStart(8)} | ${"peak%".padStart(8)} | ${"drawdown%".padStart(10)}`);
|
|
3484
|
+
console.log("-".repeat(83));
|
|
3485
|
+
for (const r of rows) {
|
|
3486
|
+
const min = String(r.min).padStart(5);
|
|
3487
|
+
const ts = new Date(r.timestamp).toISOString().padEnd(24);
|
|
3488
|
+
const close = r.close.toFixed(2).padStart(12);
|
|
3489
|
+
const pnlStr = (r.pnl >= 0 ? "+" : "") + r.pnl.toFixed(2) + "%";
|
|
3490
|
+
const peakStr = "+" + r.peak.toFixed(2) + "%";
|
|
3491
|
+
const drawdownStr = r.drawdown.toFixed(2) + "%";
|
|
3492
|
+
console.log(`${min} | ${ts} | ${close} | ${pnlStr.padStart(8)} | ${peakStr.padStart(8)} | ${drawdownStr.padStart(10)}`);
|
|
3493
|
+
}
|
|
3494
|
+
process.exit(0);
|
|
3495
|
+
};
|
|
3245
3496
|
main$3();
|
|
3246
3497
|
|
|
3247
3498
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -3360,6 +3611,7 @@ Modes:
|
|
|
3360
3611
|
--pine <entry> Execute a local .pine indicator file
|
|
3361
3612
|
--editor Open the Pine Script visual editor in the browser
|
|
3362
3613
|
--dump Fetch and save raw OHLCV candles
|
|
3614
|
+
--pnldebug Simulate PnL per minute for a given entry price and direction
|
|
3363
3615
|
--flush <entry...> Delete report/log/markdown/agent folders from strategy dump dir
|
|
3364
3616
|
--init Scaffold a new project in the current directory
|
|
3365
3617
|
--help Print this help message
|
|
@@ -3432,6 +3684,21 @@ Candle dump flags (--dump):
|
|
|
3432
3684
|
|
|
3433
3685
|
Module file ./modules/dump.module is loaded automatically if it exists.
|
|
3434
3686
|
|
|
3687
|
+
PnL debug flags (--pnldebug):
|
|
3688
|
+
|
|
3689
|
+
--symbol <string> Trading pair (default: BTCUSDT)
|
|
3690
|
+
--priceopen <number> Entry price (required)
|
|
3691
|
+
--direction <string> Position direction: long or short (default: long)
|
|
3692
|
+
--when <string> Start timestamp — ISO 8601 or Unix ms (default: now)
|
|
3693
|
+
--minutes <string> Number of 1m candles to simulate (default: 60)
|
|
3694
|
+
--exchange <string> Exchange name (default: first registered)
|
|
3695
|
+
--output <string> Output file base name (default: {SYMBOL}_{DIRECTION}_{PRICEOPEN}_{TIMESTAMP})
|
|
3696
|
+
--json Save as JSON array to ./dump/<output>.json
|
|
3697
|
+
--jsonl Save as JSONL to ./dump/<output>.jsonl
|
|
3698
|
+
--markdown Save as Markdown table to ./dump/<output>.md
|
|
3699
|
+
|
|
3700
|
+
Module file ./modules/pnldebug.module is loaded automatically if it exists.
|
|
3701
|
+
|
|
3435
3702
|
Flush flags (--flush):
|
|
3436
3703
|
|
|
3437
3704
|
One or more positional entry points. For each entry point the following
|
|
@@ -3454,6 +3721,7 @@ Module hooks (loaded automatically by each mode):
|
|
|
3454
3721
|
modules/pine.module --pine Exchange schema for PineScript runs
|
|
3455
3722
|
modules/editor.module --editor Exchange schema for the visual Pine editor
|
|
3456
3723
|
modules/dump.module --dump Exchange schema for candle dumps
|
|
3724
|
+
modules/pnldebug.module --pnldebug Exchange schema for PnL debug runs
|
|
3457
3725
|
|
|
3458
3726
|
--flush has no associated module. It only removes dump subdirectories.
|
|
3459
3727
|
|
|
@@ -3477,6 +3745,8 @@ Examples:
|
|
|
3477
3745
|
node ${ENTRY_PATH} --pine ./math/feb_2026.pine --timeframe 15m --limit 500 --jsonl
|
|
3478
3746
|
node ${ENTRY_PATH} --editor
|
|
3479
3747
|
node ${ENTRY_PATH} --dump --symbol BTCUSDT --timeframe 15m --limit 500 --jsonl
|
|
3748
|
+
node ${ENTRY_PATH} --pnldebug --symbol BTCUSDT --priceopen 64069.50 --direction short --when "2025-02-25" --minutes 120
|
|
3749
|
+
node ${ENTRY_PATH} --pnldebug --priceopen 67956.73 --direction long --when 1772064000000 --minutes 60 --markdown
|
|
3480
3750
|
node ${ENTRY_PATH} --flush ./content/feb_2026.strategy/feb_2026.strategy.ts
|
|
3481
3751
|
node ${ENTRY_PATH} --flush ./content/feb_2026.strategy/feb_2026.strategy.ts ./content/feb_2026.strategy/feb_2026.test.ts
|
|
3482
3752
|
node ${ENTRY_PATH} --init --output my-trading-bot
|
|
@@ -3489,7 +3759,7 @@ const main$1 = async () => {
|
|
|
3489
3759
|
if (!values.help) {
|
|
3490
3760
|
return;
|
|
3491
3761
|
}
|
|
3492
|
-
process.stdout.write(`@backtest-kit/cli ${"7.
|
|
3762
|
+
process.stdout.write(`@backtest-kit/cli ${"7.5.0"}\n\n`);
|
|
3493
3763
|
process.stdout.write(HELP_TEXT);
|
|
3494
3764
|
process.exit(0);
|
|
3495
3765
|
};
|
|
@@ -3503,7 +3773,7 @@ const main = async () => {
|
|
|
3503
3773
|
if (!values.version) {
|
|
3504
3774
|
return;
|
|
3505
3775
|
}
|
|
3506
|
-
process.stdout.write(`@backtest-kit/cli ${"7.
|
|
3776
|
+
process.stdout.write(`@backtest-kit/cli ${"7.5.0"}\n`);
|
|
3507
3777
|
process.exit(0);
|
|
3508
3778
|
};
|
|
3509
3779
|
main();
|