@backtest-kit/ui 12.8.0 → 13.3.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.
Files changed (41) hide show
  1. package/README.md +254 -254
  2. package/build/index.cjs +575 -0
  3. package/build/index.mjs +576 -1
  4. package/build/modules/frontend/build/3rdparty/ace_1.4.12/ace.js +21337 -21337
  5. package/build/modules/frontend/build/3rdparty/ace_1.4.12/mode-javascript.js +797 -797
  6. package/build/modules/frontend/build/3rdparty/ace_1.4.12/theme-chrome.js +137 -137
  7. package/build/modules/frontend/build/3rdparty/ace_1.4.12/theme-twilight.js +115 -115
  8. package/build/modules/frontend/build/3rdparty/ace_1.4.12/worker-javascript.js +15012 -15012
  9. package/build/modules/frontend/build/3rdparty/qfchart_0.8.7/echarts.min.js +45 -45
  10. package/build/modules/frontend/build/assets/{Article-Da78GEhK.js → Article-sbYRbQe0.js} +1 -1
  11. package/build/modules/frontend/build/assets/{Background-0ACHD5B6.js → Background-dyHMipOI.js} +1 -1
  12. package/build/modules/frontend/build/assets/{IconPhoto-BPAbqALJ.js → IconPhoto-CHqApvRw.js} +1 -1
  13. package/build/modules/frontend/build/assets/{KeyboardArrowLeft-YMeBM3Q3.js → KeyboardArrowLeft-CHOMu6qx.js} +1 -1
  14. package/build/modules/frontend/build/assets/{PictureAsPdfOutlined-CA7hIpf4.js → PictureAsPdfOutlined-DzknxeSi.js} +1 -1
  15. package/build/modules/frontend/build/assets/{Refresh-CTa-W1su.js → Refresh-DmSh3yQM.js} +1 -1
  16. package/build/modules/frontend/build/assets/emitters-BNMcCjB_.js +1 -0
  17. package/build/modules/frontend/build/assets/{hasRouteMatch-Dz1eRfX0.js → hasRouteMatch-DqwdOTLY.js} +1 -1
  18. package/build/modules/frontend/build/assets/{html2canvas-CuvtHslW.js → html2canvas-CHKh6bmw.js} +1 -1
  19. package/build/modules/frontend/build/assets/{index-fv31BaKN.js → index-0MseBgyH.js} +15 -15
  20. package/build/modules/frontend/build/assets/{index-jg7SuL7J.js → index-9MTo_fXC.js} +1 -1
  21. package/build/modules/frontend/build/assets/{index-Dye20IcA.js → index-BGUfC2GH.js} +1 -1
  22. package/build/modules/frontend/build/assets/index-BkciU9PY.js +1 -0
  23. package/build/modules/frontend/build/assets/{index-C0qezHrv.js → index-Bm2KpX4M.js} +1 -1
  24. package/build/modules/frontend/build/assets/{index-tg1njHyT.js → index-COEOSThW.js} +1 -1
  25. package/build/modules/frontend/build/assets/{index-CGTByLJp.js → index-C_bLqeg4.js} +1 -1
  26. package/build/modules/frontend/build/assets/{index-C19KVXyR.js → index-CkS6tnju.js} +1 -1
  27. package/build/modules/frontend/build/assets/index-DUb1EyrG.js +1 -0
  28. package/build/modules/frontend/build/assets/{index--CAl9k-j.js → index-DYoETulh.js} +1 -1
  29. package/build/modules/frontend/build/assets/{index-DO3lwaMI.js → index-Dq8WsVMT.js} +1 -1
  30. package/build/modules/frontend/build/assets/{index-DCkqZSEX.js → index-DrklJPOF.js} +1 -1
  31. package/build/modules/frontend/build/assets/index-DtlxmULa.js +1 -0
  32. package/build/modules/frontend/build/assets/{index.es-DtUP6yiZ.js → index.es-Bnd2KFus.js} +2 -2
  33. package/build/modules/frontend/build/assets/{markdownit-Bj4vpJSk.js → markdownit-CWkrj-EI.js} +1 -1
  34. package/build/modules/frontend/build/index.html +87 -87
  35. package/build/modules/frontend/build/manifest.json +23 -23
  36. package/package.json +118 -118
  37. package/types.d.ts +85 -0
  38. package/build/modules/frontend/build/assets/emitters-CwOzUPwS.js +0 -1
  39. package/build/modules/frontend/build/assets/index-C5c7YQ-Q.js +0 -1
  40. package/build/modules/frontend/build/assets/index-CgLCD4kl.js +0 -1
  41. package/build/modules/frontend/build/assets/index-EnF3Est3.js +0 -1
package/build/index.mjs CHANGED
@@ -7,7 +7,7 @@ import serveHandler from 'serve-handler';
7
7
  import os from 'os';
8
8
  import { createActivator } from 'di-kit';
9
9
  import * as BacktestKit from 'backtest-kit';
10
- import { alignToInterval, Exchange, listExchangeSchema, Backtest, Live, Notification, Storage, intervalStepMs, Log, lib, Heat, Strategy, Breakeven, Risk, Partial, HighestProfit, MaxDrawdown, Schedule, Performance, Sync, Walker, StorageLive, StorageBacktest, Broker, Dump, Markdown, Memory, Recent, Report, State, getConfig } from 'backtest-kit';
10
+ import { alignToInterval, Exchange, listExchangeSchema, Backtest, Live, Notification, Storage, intervalStepMs, Log, lib, Heat, Strategy, Breakeven, Risk, Partial, HighestProfit, MaxDrawdown, Schedule, Performance, Sync, Walker, StorageLive, StorageBacktest, Broker, Dump, Markdown, Memory, Recent, Report, State, getConfig, Position } from 'backtest-kit';
11
11
  import fs, { readdir, readFile } from 'fs/promises';
12
12
  import path, { join, dirname } from 'path';
13
13
  import mime from 'mime-types';
@@ -87,6 +87,7 @@ const mockServices$1 = {
87
87
  environmentMockService: Symbol("environmentMockService"),
88
88
  setupMockService: Symbol("setupMockService"),
89
89
  runtimeMockService: Symbol("runtimeMockService"),
90
+ controlMockService: Symbol("controlMockService"),
90
91
  };
91
92
  const viewServices$1 = {
92
93
  notificationViewService: Symbol("notificationViewService"),
@@ -102,6 +103,7 @@ const viewServices$1 = {
102
103
  environmentViewService: Symbol("environmentViewService"),
103
104
  setupViewService: Symbol("setupViewService"),
104
105
  runtimeViewService: Symbol("runtimeViewService"),
106
+ controlViewService: Symbol("controlViewService"),
105
107
  };
106
108
  const TYPES = {
107
109
  ...baseServices$1,
@@ -2176,6 +2178,237 @@ class RuntimeViewService {
2176
2178
  }
2177
2179
  }
2178
2180
 
2181
+ const MOCK_STRATEGY_PATH = "./mock/strategy.json";
2182
+ const MOCK_STRATEGY_INFO_PATH = "./mock/strategy-info.json";
2183
+ const READ_STRATEGY_FN = singleshot(async () => {
2184
+ const data = await fs.readFile(MOCK_STRATEGY_PATH, "utf-8");
2185
+ return JSON.parse(data);
2186
+ });
2187
+ const READ_STRATEGY_INFO_FN = singleshot(async () => {
2188
+ const data = await fs.readFile(MOCK_STRATEGY_INFO_PATH, "utf-8");
2189
+ return JSON.parse(data);
2190
+ });
2191
+ class ControlMockService {
2192
+ constructor() {
2193
+ this.loggerService = inject(TYPES.loggerService);
2194
+ this.getStatus = async (symbol, context) => {
2195
+ this.loggerService.log("controlMockService getStatus", {
2196
+ symbol,
2197
+ context,
2198
+ });
2199
+ const strategyInfo = await READ_STRATEGY_INFO_FN();
2200
+ const pendingSignal = await READ_STRATEGY_FN();
2201
+ const currentPrice = pendingSignal?.pnl?.priceClose ?? pendingSignal?.priceOpen ?? 0;
2202
+ return { strategyInfo, pendingSignal, currentPrice };
2203
+ };
2204
+ this.getAveragePrice = async (symbol, context) => {
2205
+ this.loggerService.log("controlMockService getAveragePrice", {
2206
+ symbol,
2207
+ context,
2208
+ });
2209
+ const pendingSignal = await READ_STRATEGY_FN();
2210
+ return pendingSignal?.pnl?.priceClose ?? pendingSignal?.priceOpen ?? 0;
2211
+ };
2212
+ this.commitOpenPending = async (symbol, context, dto) => {
2213
+ this.loggerService.log("controlMockService commitOpenPending", {
2214
+ symbol,
2215
+ context,
2216
+ dto,
2217
+ });
2218
+ };
2219
+ this.commitAverageBuy = async (symbol, context, dto) => {
2220
+ this.loggerService.log("controlMockService commitAverageBuy", {
2221
+ symbol,
2222
+ context,
2223
+ dto,
2224
+ });
2225
+ };
2226
+ this.commitClosePending = async (symbol, context, dto) => {
2227
+ this.loggerService.log("controlMockService commitClosePending", {
2228
+ symbol,
2229
+ context,
2230
+ dto,
2231
+ });
2232
+ };
2233
+ this.commitBreakeven = async (symbol, context) => {
2234
+ this.loggerService.log("controlMockService commitBreakeven", {
2235
+ symbol,
2236
+ context,
2237
+ });
2238
+ };
2239
+ }
2240
+ }
2241
+
2242
+ /** Grid step (percent) the hard stop-loss distance snaps to. */
2243
+ const HARD_STOP_STEP_PERCENT = 2.5;
2244
+ /**
2245
+ * Computes the hard stop-loss distance percent for an opened position.
2246
+ *
2247
+ * Snaps the configured max stop-loss distance to a {@link HARD_STOP_STEP_PERCENT} grid
2248
+ * (rounded to the nearest step), then steps one notch down so the result stays strictly
2249
+ * below CC_MAX_STOPLOSS_DISTANCE_PERCENT — which the signal validator rejects at the
2250
+ * boundary (e.g. 20% config yields 20.008% after price rounding).
2251
+ *
2252
+ * @param maxDistance - CC_MAX_STOPLOSS_DISTANCE_PERCENT
2253
+ * @returns Hard stop-loss distance in percent (e.g. 11 -> 7.5, 10 -> 7.5, 20 -> 17.5)
2254
+ */
2255
+ const COMPUTE_HARD_STOP_FN = (maxDistance) => Math.round(maxDistance / HARD_STOP_STEP_PERCENT) * HARD_STOP_STEP_PERCENT - HARD_STOP_STEP_PERCENT;
2256
+ class ControlViewService {
2257
+ constructor() {
2258
+ this.loggerService = inject(TYPES.loggerService);
2259
+ this.controlMockService = inject(TYPES.controlMockService);
2260
+ this.getStatus = async (symbol, context) => {
2261
+ this.loggerService.log("controlViewService getStatus", {
2262
+ symbol,
2263
+ context,
2264
+ });
2265
+ if (CC_ENABLE_MOCK) {
2266
+ return await this.controlMockService.getStatus(symbol, context);
2267
+ }
2268
+ const liveList = await Live.list();
2269
+ const liveTarget = liveList.find((live) => live.symbol === symbol);
2270
+ if (liveTarget) {
2271
+ const currentPrice = await Exchange.getAveragePrice(symbol, {
2272
+ exchangeName: liveTarget.exchangeName,
2273
+ });
2274
+ const strategy = await Live.getStrategyStatus(symbol, context);
2275
+ const pending = await Live.getPendingSignal(symbol, currentPrice, context);
2276
+ return { strategyInfo: strategy, pendingSignal: pending, currentPrice };
2277
+ }
2278
+ throw new Error("ControlViewService getStatus live target not found");
2279
+ };
2280
+ this.getAveragePrice = async (symbol, context) => {
2281
+ this.loggerService.log("controlViewService getAveragePrice", {
2282
+ symbol,
2283
+ context,
2284
+ });
2285
+ if (CC_ENABLE_MOCK) {
2286
+ return await this.controlMockService.getAveragePrice(symbol, context);
2287
+ }
2288
+ const liveList = await Live.list();
2289
+ const liveTarget = liveList.find((live) => live.symbol === symbol);
2290
+ if (liveTarget) {
2291
+ return await Exchange.getAveragePrice(symbol, {
2292
+ exchangeName: liveTarget.exchangeName,
2293
+ });
2294
+ }
2295
+ throw new Error("ControlViewService getAveragePrice live target not found");
2296
+ };
2297
+ this.commitOpenPending = async (symbol, context, dto) => {
2298
+ this.loggerService.log("controlViewService commitOpenPending", {
2299
+ symbol,
2300
+ context,
2301
+ dto,
2302
+ });
2303
+ if (CC_ENABLE_MOCK) {
2304
+ return await this.controlMockService.commitOpenPending(symbol, context, dto);
2305
+ }
2306
+ const liveList = await Live.list();
2307
+ const liveTarget = liveList.find((live) => live.symbol === symbol);
2308
+ if (liveTarget) {
2309
+ const currentPrice = await Exchange.getAveragePrice(symbol, {
2310
+ exchangeName: liveTarget.exchangeName,
2311
+ });
2312
+ const pending = await Live.getPendingSignal(symbol, currentPrice, context);
2313
+ const config = getConfig();
2314
+ if (pending) {
2315
+ throw new Error("ControlViewService commitOpenPending already have pending signal");
2316
+ }
2317
+ const percentStopLoss = COMPUTE_HARD_STOP_FN(config.CC_MAX_STOPLOSS_DISTANCE_PERCENT);
2318
+ return await Live.commitCreateSignal(symbol, context, {
2319
+ ...Position.moonbag({
2320
+ position: dto.position,
2321
+ currentPrice,
2322
+ percentStopLoss,
2323
+ }),
2324
+ cost: dto.cost,
2325
+ note: dto.note,
2326
+ });
2327
+ }
2328
+ throw new Error("ControlViewService commitOpenPending live target not found");
2329
+ };
2330
+ this.commitAverageBuy = async (symbol, context, dto) => {
2331
+ this.loggerService.log("controlViewService commitAverageBuy", {
2332
+ symbol,
2333
+ context,
2334
+ dto,
2335
+ });
2336
+ if (CC_ENABLE_MOCK) {
2337
+ return await this.controlMockService.commitAverageBuy(symbol, context, dto);
2338
+ }
2339
+ const liveList = await Live.list();
2340
+ const liveTarget = liveList.find((live) => live.symbol === symbol);
2341
+ if (liveTarget) {
2342
+ const currentPrice = await Exchange.getAveragePrice(symbol, {
2343
+ exchangeName: liveTarget.exchangeName,
2344
+ });
2345
+ const pending = await Live.getPendingSignal(symbol, currentPrice, context);
2346
+ if (!pending) {
2347
+ throw new Error("ControlViewService commitAverageBuy has no pending signal");
2348
+ }
2349
+ const isOk = await Live.commitAverageBuy(symbol, currentPrice, context, dto.cost);
2350
+ if (!isOk) {
2351
+ throw new Error("ControlViewService commitAverageBuy failed");
2352
+ }
2353
+ return;
2354
+ }
2355
+ throw new Error("ControlViewService commitAverageBuy live target not found");
2356
+ };
2357
+ this.commitClosePending = async (symbol, context, dto) => {
2358
+ this.loggerService.log("controlViewService commitClosePending", {
2359
+ symbol,
2360
+ context,
2361
+ dto,
2362
+ });
2363
+ if (CC_ENABLE_MOCK) {
2364
+ return await this.controlMockService.commitClosePending(symbol, context, dto);
2365
+ }
2366
+ const liveList = await Live.list();
2367
+ const liveTarget = liveList.find((live) => live.symbol === symbol);
2368
+ if (liveTarget) {
2369
+ const currentPrice = await Exchange.getAveragePrice(symbol, {
2370
+ exchangeName: liveTarget.exchangeName,
2371
+ });
2372
+ const pending = await Live.getPendingSignal(symbol, currentPrice, context);
2373
+ if (!pending) {
2374
+ throw new Error("ControlViewService commitClosePending has no pending signal");
2375
+ }
2376
+ return await Live.commitClosePending(symbol, context, {
2377
+ id: pending.id,
2378
+ note: dto.note,
2379
+ });
2380
+ }
2381
+ throw new Error("ControlViewService commitClosePending live target not found");
2382
+ };
2383
+ this.commitBreakeven = async (symbol, context) => {
2384
+ this.loggerService.log("controlViewService commitBreakeven", {
2385
+ symbol,
2386
+ context,
2387
+ });
2388
+ if (CC_ENABLE_MOCK) {
2389
+ return await this.controlMockService.commitBreakeven(symbol, context);
2390
+ }
2391
+ const liveList = await Live.list();
2392
+ const liveTarget = liveList.find((live) => live.symbol === symbol);
2393
+ if (liveTarget) {
2394
+ const currentPrice = await Exchange.getAveragePrice(symbol, {
2395
+ exchangeName: liveTarget.exchangeName,
2396
+ });
2397
+ const pending = await Live.getPendingSignal(symbol, currentPrice, context);
2398
+ if (!pending) {
2399
+ throw new Error("ControlViewService commitBreakeven has no pending signal");
2400
+ }
2401
+ const isOk = await Live.commitBreakeven(symbol, currentPrice, context);
2402
+ if (!isOk) {
2403
+ throw new Error("ControlViewService commitBreakeven failed");
2404
+ }
2405
+ return;
2406
+ }
2407
+ throw new Error("ControlViewService commitBreakeven live target not found");
2408
+ };
2409
+ }
2410
+ }
2411
+
2179
2412
  {
2180
2413
  provide(TYPES.loggerService, () => new LoggerService());
2181
2414
  provide(TYPES.exchangeService, () => new ExchangeService());
@@ -2203,6 +2436,7 @@ class RuntimeViewService {
2203
2436
  provide(TYPES.environmentMockService, () => new EnvironmentMockService());
2204
2437
  provide(TYPES.setupMockService, () => new SetupMockService());
2205
2438
  provide(TYPES.runtimeMockService, () => new RuntimeMockService());
2439
+ provide(TYPES.controlMockService, () => new ControlMockService());
2206
2440
  }
2207
2441
  {
2208
2442
  provide(TYPES.notificationViewService, () => new NotificationViewService());
@@ -2218,6 +2452,7 @@ class RuntimeViewService {
2218
2452
  provide(TYPES.environmentViewService, () => new EnvironmentViewService());
2219
2453
  provide(TYPES.setupViewService, () => new SetupViewService());
2220
2454
  provide(TYPES.runtimeViewService, () => new RuntimeViewService());
2455
+ provide(TYPES.controlViewService, () => new ControlViewService());
2221
2456
  }
2222
2457
 
2223
2458
  const baseServices = {
@@ -2247,6 +2482,7 @@ const mockServices = {
2247
2482
  environmentMockService: inject(TYPES.environmentMockService),
2248
2483
  setupMockService: inject(TYPES.setupMockService),
2249
2484
  runtimeMockService: inject(TYPES.runtimeMockService),
2485
+ controlMockService: inject(TYPES.controlMockService),
2250
2486
  };
2251
2487
  const viewServices = {
2252
2488
  notificationViewService: inject(TYPES.notificationViewService),
@@ -2262,6 +2498,7 @@ const viewServices = {
2262
2498
  environmentViewService: inject(TYPES.environmentViewService),
2263
2499
  setupViewService: inject(TYPES.setupViewService),
2264
2500
  runtimeViewService: inject(TYPES.runtimeViewService),
2501
+ controlViewService: inject(TYPES.controlViewService),
2265
2502
  };
2266
2503
  const ioc = {
2267
2504
  ...baseServices,
@@ -2830,6 +3067,175 @@ router$b.post("/api/v1/mock/status_one/:id", async (req, res) => {
2830
3067
  });
2831
3068
  }
2832
3069
  });
3070
+ // ControlMockService endpoints
3071
+ router$b.post("/api/v1/mock/control_status", async (req, res) => {
3072
+ try {
3073
+ const request = await micro.json(req);
3074
+ const { symbol, context, requestId, serviceName } = request;
3075
+ const data = await ioc.controlMockService.getStatus(symbol, context);
3076
+ const result = {
3077
+ data,
3078
+ status: "ok",
3079
+ error: "",
3080
+ requestId,
3081
+ serviceName,
3082
+ };
3083
+ ioc.loggerService.log("/api/v1/mock/control_status ok", {
3084
+ request,
3085
+ result: omit(result, "data"),
3086
+ });
3087
+ return await micro.send(res, 200, result);
3088
+ }
3089
+ catch (error) {
3090
+ ioc.loggerService.log("/api/v1/mock/control_status error", {
3091
+ error: errorData(error),
3092
+ });
3093
+ return await micro.send(res, 200, {
3094
+ status: "error",
3095
+ error: getErrorMessage(error),
3096
+ });
3097
+ }
3098
+ });
3099
+ router$b.post("/api/v1/mock/control_average_price", async (req, res) => {
3100
+ try {
3101
+ const request = await micro.json(req);
3102
+ const { symbol, context, requestId, serviceName } = request;
3103
+ const data = await ioc.controlMockService.getAveragePrice(symbol, context);
3104
+ const result = {
3105
+ data,
3106
+ status: "ok",
3107
+ error: "",
3108
+ requestId,
3109
+ serviceName,
3110
+ };
3111
+ ioc.loggerService.log("/api/v1/mock/control_average_price ok", {
3112
+ request,
3113
+ result: omit(result, "data"),
3114
+ });
3115
+ return await micro.send(res, 200, result);
3116
+ }
3117
+ catch (error) {
3118
+ ioc.loggerService.log("/api/v1/mock/control_average_price error", {
3119
+ error: errorData(error),
3120
+ });
3121
+ return await micro.send(res, 200, {
3122
+ status: "error",
3123
+ error: getErrorMessage(error),
3124
+ });
3125
+ }
3126
+ });
3127
+ router$b.post("/api/v1/mock/control_open_pending", async (req, res) => {
3128
+ try {
3129
+ const request = await micro.json(req);
3130
+ const { symbol, context, dto, requestId, serviceName } = request;
3131
+ const data = await ioc.controlMockService.commitOpenPending(symbol, context, dto);
3132
+ const result = {
3133
+ data,
3134
+ status: "ok",
3135
+ error: "",
3136
+ requestId,
3137
+ serviceName,
3138
+ };
3139
+ ioc.loggerService.log("/api/v1/mock/control_open_pending ok", {
3140
+ request,
3141
+ result: omit(result, "data"),
3142
+ });
3143
+ return await micro.send(res, 200, result);
3144
+ }
3145
+ catch (error) {
3146
+ ioc.loggerService.log("/api/v1/mock/control_open_pending error", {
3147
+ error: errorData(error),
3148
+ });
3149
+ return await micro.send(res, 200, {
3150
+ status: "error",
3151
+ error: getErrorMessage(error),
3152
+ });
3153
+ }
3154
+ });
3155
+ router$b.post("/api/v1/mock/control_average_buy", async (req, res) => {
3156
+ try {
3157
+ const request = await micro.json(req);
3158
+ const { symbol, context, dto, requestId, serviceName } = request;
3159
+ const data = await ioc.controlMockService.commitAverageBuy(symbol, context, dto);
3160
+ const result = {
3161
+ data,
3162
+ status: "ok",
3163
+ error: "",
3164
+ requestId,
3165
+ serviceName,
3166
+ };
3167
+ ioc.loggerService.log("/api/v1/mock/control_average_buy ok", {
3168
+ request,
3169
+ result: omit(result, "data"),
3170
+ });
3171
+ return await micro.send(res, 200, result);
3172
+ }
3173
+ catch (error) {
3174
+ ioc.loggerService.log("/api/v1/mock/control_average_buy error", {
3175
+ error: errorData(error),
3176
+ });
3177
+ return await micro.send(res, 200, {
3178
+ status: "error",
3179
+ error: getErrorMessage(error),
3180
+ });
3181
+ }
3182
+ });
3183
+ router$b.post("/api/v1/mock/control_close_pending", async (req, res) => {
3184
+ try {
3185
+ const request = await micro.json(req);
3186
+ const { symbol, context, dto, requestId, serviceName } = request;
3187
+ const data = await ioc.controlMockService.commitClosePending(symbol, context, dto);
3188
+ const result = {
3189
+ data,
3190
+ status: "ok",
3191
+ error: "",
3192
+ requestId,
3193
+ serviceName,
3194
+ };
3195
+ ioc.loggerService.log("/api/v1/mock/control_close_pending ok", {
3196
+ request,
3197
+ result: omit(result, "data"),
3198
+ });
3199
+ return await micro.send(res, 200, result);
3200
+ }
3201
+ catch (error) {
3202
+ ioc.loggerService.log("/api/v1/mock/control_close_pending error", {
3203
+ error: errorData(error),
3204
+ });
3205
+ return await micro.send(res, 200, {
3206
+ status: "error",
3207
+ error: getErrorMessage(error),
3208
+ });
3209
+ }
3210
+ });
3211
+ router$b.post("/api/v1/mock/control_breakeven", async (req, res) => {
3212
+ try {
3213
+ const request = await micro.json(req);
3214
+ const { symbol, context, requestId, serviceName } = request;
3215
+ const data = await ioc.controlMockService.commitBreakeven(symbol, context);
3216
+ const result = {
3217
+ data,
3218
+ status: "ok",
3219
+ error: "",
3220
+ requestId,
3221
+ serviceName,
3222
+ };
3223
+ ioc.loggerService.log("/api/v1/mock/control_breakeven ok", {
3224
+ request,
3225
+ result: omit(result, "data"),
3226
+ });
3227
+ return await micro.send(res, 200, result);
3228
+ }
3229
+ catch (error) {
3230
+ ioc.loggerService.log("/api/v1/mock/control_breakeven error", {
3231
+ error: errorData(error),
3232
+ });
3233
+ return await micro.send(res, 200, {
3234
+ status: "error",
3235
+ error: getErrorMessage(error),
3236
+ });
3237
+ }
3238
+ });
2833
3239
  // HeatMockService endpoints
2834
3240
  router$b.post("/api/v1/mock/heat_data", async (req, res) => {
2835
3241
  try {
@@ -3589,6 +3995,175 @@ router$a.post("/api/v1/view/status_one/:id", async (req, res) => {
3589
3995
  });
3590
3996
  }
3591
3997
  });
3998
+ // ControlViewService endpoints
3999
+ router$a.post("/api/v1/view/control_status", async (req, res) => {
4000
+ try {
4001
+ const request = await micro.json(req);
4002
+ const { symbol, context, requestId, serviceName } = request;
4003
+ const data = await ioc.controlViewService.getStatus(symbol, context);
4004
+ const result = {
4005
+ data,
4006
+ status: "ok",
4007
+ error: "",
4008
+ requestId,
4009
+ serviceName,
4010
+ };
4011
+ ioc.loggerService.log("/api/v1/view/control_status ok", {
4012
+ request,
4013
+ result: omit(result, "data"),
4014
+ });
4015
+ return await micro.send(res, 200, result);
4016
+ }
4017
+ catch (error) {
4018
+ ioc.loggerService.log("/api/v1/view/control_status error", {
4019
+ error: errorData(error),
4020
+ });
4021
+ return await micro.send(res, 200, {
4022
+ status: "error",
4023
+ error: getErrorMessage(error),
4024
+ });
4025
+ }
4026
+ });
4027
+ router$a.post("/api/v1/view/control_average_price", async (req, res) => {
4028
+ try {
4029
+ const request = await micro.json(req);
4030
+ const { symbol, context, requestId, serviceName } = request;
4031
+ const data = await ioc.controlViewService.getAveragePrice(symbol, context);
4032
+ const result = {
4033
+ data,
4034
+ status: "ok",
4035
+ error: "",
4036
+ requestId,
4037
+ serviceName,
4038
+ };
4039
+ ioc.loggerService.log("/api/v1/view/control_average_price ok", {
4040
+ request,
4041
+ result: omit(result, "data"),
4042
+ });
4043
+ return await micro.send(res, 200, result);
4044
+ }
4045
+ catch (error) {
4046
+ ioc.loggerService.log("/api/v1/view/control_average_price error", {
4047
+ error: errorData(error),
4048
+ });
4049
+ return await micro.send(res, 200, {
4050
+ status: "error",
4051
+ error: getErrorMessage(error),
4052
+ });
4053
+ }
4054
+ });
4055
+ router$a.post("/api/v1/view/control_open_pending", async (req, res) => {
4056
+ try {
4057
+ const request = await micro.json(req);
4058
+ const { symbol, context, dto, requestId, serviceName } = request;
4059
+ const data = await ioc.controlViewService.commitOpenPending(symbol, context, dto);
4060
+ const result = {
4061
+ data,
4062
+ status: "ok",
4063
+ error: "",
4064
+ requestId,
4065
+ serviceName,
4066
+ };
4067
+ ioc.loggerService.log("/api/v1/view/control_open_pending ok", {
4068
+ request,
4069
+ result: omit(result, "data"),
4070
+ });
4071
+ return await micro.send(res, 200, result);
4072
+ }
4073
+ catch (error) {
4074
+ ioc.loggerService.log("/api/v1/view/control_open_pending error", {
4075
+ error: errorData(error),
4076
+ });
4077
+ return await micro.send(res, 200, {
4078
+ status: "error",
4079
+ error: getErrorMessage(error),
4080
+ });
4081
+ }
4082
+ });
4083
+ router$a.post("/api/v1/view/control_average_buy", async (req, res) => {
4084
+ try {
4085
+ const request = await micro.json(req);
4086
+ const { symbol, context, dto, requestId, serviceName } = request;
4087
+ const data = await ioc.controlViewService.commitAverageBuy(symbol, context, dto);
4088
+ const result = {
4089
+ data,
4090
+ status: "ok",
4091
+ error: "",
4092
+ requestId,
4093
+ serviceName,
4094
+ };
4095
+ ioc.loggerService.log("/api/v1/view/control_average_buy ok", {
4096
+ request,
4097
+ result: omit(result, "data"),
4098
+ });
4099
+ return await micro.send(res, 200, result);
4100
+ }
4101
+ catch (error) {
4102
+ ioc.loggerService.log("/api/v1/view/control_average_buy error", {
4103
+ error: errorData(error),
4104
+ });
4105
+ return await micro.send(res, 200, {
4106
+ status: "error",
4107
+ error: getErrorMessage(error),
4108
+ });
4109
+ }
4110
+ });
4111
+ router$a.post("/api/v1/view/control_close_pending", async (req, res) => {
4112
+ try {
4113
+ const request = await micro.json(req);
4114
+ const { symbol, context, dto, requestId, serviceName } = request;
4115
+ const data = await ioc.controlViewService.commitClosePending(symbol, context, dto);
4116
+ const result = {
4117
+ data,
4118
+ status: "ok",
4119
+ error: "",
4120
+ requestId,
4121
+ serviceName,
4122
+ };
4123
+ ioc.loggerService.log("/api/v1/view/control_close_pending ok", {
4124
+ request,
4125
+ result: omit(result, "data"),
4126
+ });
4127
+ return await micro.send(res, 200, result);
4128
+ }
4129
+ catch (error) {
4130
+ ioc.loggerService.log("/api/v1/view/control_close_pending error", {
4131
+ error: errorData(error),
4132
+ });
4133
+ return await micro.send(res, 200, {
4134
+ status: "error",
4135
+ error: getErrorMessage(error),
4136
+ });
4137
+ }
4138
+ });
4139
+ router$a.post("/api/v1/view/control_breakeven", async (req, res) => {
4140
+ try {
4141
+ const request = await micro.json(req);
4142
+ const { symbol, context, requestId, serviceName } = request;
4143
+ const data = await ioc.controlViewService.commitBreakeven(symbol, context);
4144
+ const result = {
4145
+ data,
4146
+ status: "ok",
4147
+ error: "",
4148
+ requestId,
4149
+ serviceName,
4150
+ };
4151
+ ioc.loggerService.log("/api/v1/view/control_breakeven ok", {
4152
+ request,
4153
+ result: omit(result, "data"),
4154
+ });
4155
+ return await micro.send(res, 200, result);
4156
+ }
4157
+ catch (error) {
4158
+ ioc.loggerService.log("/api/v1/view/control_breakeven error", {
4159
+ error: errorData(error),
4160
+ });
4161
+ return await micro.send(res, 200, {
4162
+ status: "error",
4163
+ error: getErrorMessage(error),
4164
+ });
4165
+ }
4166
+ });
3592
4167
  // HeatViewService endpoints
3593
4168
  router$a.post("/api/v1/view/heat_data", async (req, res) => {
3594
4169
  try {