@gbozee/ultimate 0.0.2-130 → 0.0.2-131

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.
@@ -599,6 +599,33 @@ export declare function getOptimumHedgeFactor(payload: {
599
599
  iterations: number;
600
600
  converged: boolean;
601
601
  };
602
+ export type CType = {
603
+ next_order: number;
604
+ take_profit: number;
605
+ };
606
+ export declare function determineCompoundLongTrade(payload: {
607
+ focus_short_position: CType;
608
+ focus_long_position: CType;
609
+ shortConfig: {
610
+ entry: number;
611
+ stop: number;
612
+ risk_reward: number;
613
+ risk: number;
614
+ symbol: string;
615
+ profit_percent: number;
616
+ };
617
+ rr?: number;
618
+ global_config: GlobalConfig;
619
+ }): {
620
+ start_risk: number;
621
+ short_profit: number;
622
+ support: number;
623
+ resistance: number;
624
+ long_v: any;
625
+ profit_percent: number;
626
+ result: any;
627
+ short_max_size: any;
628
+ };
602
629
  export type StrategyPosition = {
603
630
  entry: number;
604
631
  quantity: number;
@@ -2132,6 +2132,52 @@ function getOptimumHedgeFactor(payload) {
2132
2132
  converged: best_diff <= tolerance
2133
2133
  };
2134
2134
  }
2135
+ function determineCompoundLongTrade(payload) {
2136
+ const {
2137
+ focus_short_position,
2138
+ focus_long_position,
2139
+ shortConfig,
2140
+ global_config,
2141
+ rr = 1
2142
+ } = payload;
2143
+ const short_app_config = buildAppConfig(global_config, {
2144
+ entry: shortConfig.entry,
2145
+ stop: shortConfig.stop,
2146
+ risk_reward: shortConfig.risk_reward,
2147
+ risk: shortConfig.risk,
2148
+ symbol: shortConfig.symbol
2149
+ });
2150
+ const short_max_size = short_app_config.last_value.avg_size;
2151
+ const start_risk = Math.abs(short_app_config.last_value.neg_pnl) * rr;
2152
+ const short_profit = short_app_config.last_value.avg_size * short_app_config.last_value.avg_entry * shortConfig.profit_percent / 100;
2153
+ const support = Math.abs(short_app_config.last_value.avg_entry - short_profit) * rr;
2154
+ const resistance = focus_short_position.next_order || focus_long_position.take_profit;
2155
+ const result = getRiskReward({
2156
+ entry: resistance,
2157
+ stop: support,
2158
+ risk: start_risk,
2159
+ global_config,
2160
+ force_exact_risk: true
2161
+ });
2162
+ const long_app_config = buildAppConfig(global_config, {
2163
+ entry: resistance,
2164
+ stop: support,
2165
+ risk_reward: result.risk_reward,
2166
+ risk: result.risk,
2167
+ symbol: shortConfig.symbol
2168
+ });
2169
+ const long_profit_percent = start_risk * 2 * 100 / (long_app_config.last_value.avg_size * long_app_config.last_value.avg_entry);
2170
+ return {
2171
+ start_risk,
2172
+ short_profit,
2173
+ support: to_f(support, global_config.price_places),
2174
+ resistance: to_f(resistance, global_config.price_places),
2175
+ long_v: long_app_config.last_value,
2176
+ profit_percent: to_f(long_profit_percent, "%.3f"),
2177
+ result,
2178
+ short_max_size
2179
+ };
2180
+ }
2135
2181
  // src/helpers/strategy.ts
2136
2182
  class Strategy {
2137
2183
  position;
@@ -2665,6 +2711,7 @@ export {
2665
2711
  determineRewardFactor,
2666
2712
  determineOptimumRisk,
2667
2713
  determineOptimumReward,
2714
+ determineCompoundLongTrade,
2668
2715
  createGapPairs,
2669
2716
  createArray,
2670
2717
  computeTotalAverageForEachTrade,
package/dist/index.cjs CHANGED
@@ -41963,6 +41963,7 @@ __export(exports_src, {
41963
41963
  determineRewardFactor: () => determineRewardFactor,
41964
41964
  determineOptimumRisk: () => determineOptimumRisk,
41965
41965
  determineOptimumReward: () => determineOptimumReward,
41966
+ determineCompoundLongTrade: () => determineCompoundLongTrade,
41966
41967
  database: () => exports_database,
41967
41968
  createArray: () => createArray,
41968
41969
  computeRiskReward: () => computeRiskReward,
@@ -52484,6 +52485,37 @@ class AppDatabase {
52484
52485
  });
52485
52486
  return result;
52486
52487
  }
52488
+ async getPositionWithLowestNextOrder(options) {
52489
+ const { symbol, kind, asset, exclude } = options;
52490
+ try {
52491
+ let filter = `kind="${kind}" && next_order != null`;
52492
+ if (asset) {
52493
+ filter += ` && symbol ~ "${asset.toUpperCase()}%"`;
52494
+ } else if (symbol) {
52495
+ filter += ` && symbol:lower="${symbol.toLowerCase()}"`;
52496
+ } else {
52497
+ throw new Error("Either symbol or asset must be provided");
52498
+ }
52499
+ if (exclude && exclude.length > 0) {
52500
+ const excludeConditions = exclude.map((acc) => `(p_account.owner:lower != "${acc.owner.toLowerCase()}" || p_account.exchange:lower != "${acc.exchange.toLowerCase()}")`).join(" && ");
52501
+ filter += ` && (${excludeConditions})`;
52502
+ }
52503
+ const sortDirection = kind === "short" ? "+" : "-";
52504
+ const positions = await this.pb.collection("positions_view").getList(1, 1, {
52505
+ filter,
52506
+ sort: `${sortDirection}next_order`,
52507
+ expand: "p_account"
52508
+ });
52509
+ if (positions.items.length > 0) {
52510
+ return positions.items[0];
52511
+ }
52512
+ return null;
52513
+ } catch (error) {
52514
+ const identifier = asset ? `asset ${asset}` : `symbol ${symbol}`;
52515
+ console.error(`Error fetching position with ${kind === "short" ? "lowest" : "highest"} next_order for ${identifier} ${kind}:`, error);
52516
+ return null;
52517
+ }
52518
+ }
52487
52519
  async hasExistingOrders(symbol) {
52488
52520
  const result = await this.pb.collection("orders").getFullList({
52489
52521
  filter: `symbol:lower="${symbol.toLowerCase()}"`
@@ -54437,6 +54469,52 @@ function getOptimumHedgeFactor(payload) {
54437
54469
  converged: best_diff <= tolerance
54438
54470
  };
54439
54471
  }
54472
+ function determineCompoundLongTrade(payload) {
54473
+ const {
54474
+ focus_short_position,
54475
+ focus_long_position,
54476
+ shortConfig,
54477
+ global_config,
54478
+ rr = 1
54479
+ } = payload;
54480
+ const short_app_config = buildAppConfig(global_config, {
54481
+ entry: shortConfig.entry,
54482
+ stop: shortConfig.stop,
54483
+ risk_reward: shortConfig.risk_reward,
54484
+ risk: shortConfig.risk,
54485
+ symbol: shortConfig.symbol
54486
+ });
54487
+ const short_max_size = short_app_config.last_value.avg_size;
54488
+ const start_risk = Math.abs(short_app_config.last_value.neg_pnl) * rr;
54489
+ const short_profit = short_app_config.last_value.avg_size * short_app_config.last_value.avg_entry * shortConfig.profit_percent / 100;
54490
+ const support = Math.abs(short_app_config.last_value.avg_entry - short_profit) * rr;
54491
+ const resistance = focus_short_position.next_order || focus_long_position.take_profit;
54492
+ const result = getRiskReward({
54493
+ entry: resistance,
54494
+ stop: support,
54495
+ risk: start_risk,
54496
+ global_config,
54497
+ force_exact_risk: true
54498
+ });
54499
+ const long_app_config = buildAppConfig(global_config, {
54500
+ entry: resistance,
54501
+ stop: support,
54502
+ risk_reward: result.risk_reward,
54503
+ risk: result.risk,
54504
+ symbol: shortConfig.symbol
54505
+ });
54506
+ const long_profit_percent = start_risk * 2 * 100 / (long_app_config.last_value.avg_size * long_app_config.last_value.avg_entry);
54507
+ return {
54508
+ start_risk,
54509
+ short_profit,
54510
+ support: to_f2(support, global_config.price_places),
54511
+ resistance: to_f2(resistance, global_config.price_places),
54512
+ long_v: long_app_config.last_value,
54513
+ profit_percent: to_f2(long_profit_percent, "%.3f"),
54514
+ result,
54515
+ short_max_size
54516
+ };
54517
+ }
54440
54518
 
54441
54519
  // src/helpers/strategy.ts
54442
54520
  class Strategy {
@@ -58520,6 +58598,10 @@ class ExchangeAccount {
58520
58598
  symbol,
58521
58599
  kind
58522
58600
  });
58601
+ await this.updateRiskOnEmpty({
58602
+ symbol,
58603
+ kind
58604
+ });
58523
58605
  }
58524
58606
  const long_config = await this.getPositionConfig({
58525
58607
  symbol,
@@ -59011,17 +59093,53 @@ class ExchangeAccount {
59011
59093
  if (position2?.expand?.config) {
59012
59094
  const config2 = position2.expand.config;
59013
59095
  let _profit = config2.profit;
59096
+ let risk = config2.risk;
59097
+ let next_risk = position2.next_risk;
59014
59098
  let _profit_percent = config2?.profit_percent;
59015
59099
  if (_profit_percent && (position2?.quantity || 0) > 0) {
59016
59100
  _profit = to_f2(position2.quantity * _profit_percent * position2.entry / 100);
59101
+ next_risk = risk + _profit;
59017
59102
  }
59018
59103
  await this.app_db.update_db_position(position2, {
59019
- target_pnl: _profit
59104
+ target_pnl: _profit,
59105
+ next_risk
59020
59106
  });
59021
59107
  return _profit;
59022
59108
  }
59023
59109
  return 0;
59024
59110
  }
59111
+ async updateRiskOnEmpty(payload) {
59112
+ const { symbol, kind } = payload;
59113
+ const position2 = await this.syncAccount({
59114
+ symbol,
59115
+ kind
59116
+ });
59117
+ if (position2 && position2.quantity === 0) {
59118
+ if (position2.next_risk && position2.next_risk > 0) {
59119
+ await this.getPositionConfig({
59120
+ symbol,
59121
+ kind,
59122
+ params: {
59123
+ risk: position2.next_risk
59124
+ }
59125
+ });
59126
+ console.log(`Updated ${kind} position config for ${symbol}: risk = ${position2.next_risk}`);
59127
+ return {
59128
+ updated: true,
59129
+ symbol,
59130
+ kind,
59131
+ old_risk: position2.expand?.config?.risk,
59132
+ new_risk: position2.next_risk
59133
+ };
59134
+ }
59135
+ }
59136
+ return {
59137
+ updated: false,
59138
+ symbol,
59139
+ kind,
59140
+ reason: position2 ? position2.quantity > 0 ? "Position not empty" : "No next_risk available" : "Position not found"
59141
+ };
59142
+ }
59025
59143
  async updateGoodHedgeConfig(payload) {
59026
59144
  const {
59027
59145
  params,
@@ -60077,6 +60195,38 @@ class ExchangeAccount {
60077
60195
  decimal_places: symbol_config.decimal_places
60078
60196
  });
60079
60197
  }
60198
+ async placeCompoundShortTrade(payload) {
60199
+ }
60200
+ async placeCompoundLongTrade(payload) {
60201
+ const { symbol, params, place = false } = payload;
60202
+ if (place) {
60203
+ await this.getPositionConfig({
60204
+ symbol,
60205
+ kind: "long",
60206
+ params: {
60207
+ entry: params.resistance,
60208
+ stop: params.support,
60209
+ risk_reward: params.risk_reward,
60210
+ risk: params.risk,
60211
+ profit_percent: params.profit_percent
60212
+ }
60213
+ });
60214
+ const short_position = await this.syncAccount({
60215
+ symbol,
60216
+ kind: "short",
60217
+ as_view: true
60218
+ });
60219
+ if (short_position.quantity >= short_position.avg_qty) {
60220
+ await this.placeTrade({
60221
+ symbol,
60222
+ kind: "long",
60223
+ ignore_config: true,
60224
+ limit: true,
60225
+ place: true
60226
+ });
60227
+ }
60228
+ }
60229
+ }
60080
60230
  }
60081
60231
  function getExchangeKlass(exchange) {
60082
60232
  const func = exchange === "binance" ? BinanceExchange : BybitExchange;
@@ -60417,6 +60567,43 @@ class App {
60417
60567
  });
60418
60568
  return result;
60419
60569
  }
60570
+ async compoundLongTrade(payload) {
60571
+ const { main_account, focus_account, rr, place } = payload;
60572
+ const main_exchange_account = await this.getExchangeAccount(main_account);
60573
+ const focus_exchange_account = await this.getExchangeAccount(focus_account);
60574
+ const focus_position = await focus_exchange_account.syncAccount({
60575
+ symbol: focus_account.symbol,
60576
+ as_view: true
60577
+ });
60578
+ const focus_long_position = focus_position.find((k) => k.kind === "long");
60579
+ const focus_short_position = focus_position.find((k) => k.kind === "short");
60580
+ const shortConfig = await main_exchange_account.getPositionConfig({
60581
+ symbol: main_account.symbol,
60582
+ kind: "short"
60583
+ });
60584
+ const symbol_config = await focus_exchange_account.recomputeSymbolConfig({
60585
+ symbol: focus_account.symbol
60586
+ });
60587
+ const result = determineCompoundLongTrade({
60588
+ focus_short_position,
60589
+ focus_long_position,
60590
+ shortConfig,
60591
+ global_config: symbol_config,
60592
+ rr
60593
+ });
60594
+ await main_exchange_account.placeCompoundLongTrade({
60595
+ symbol: main_account.symbol,
60596
+ params: {
60597
+ resistance: result.resistance,
60598
+ support: result.support,
60599
+ profit_percent: result.profit_percent,
60600
+ risk_reward: result.result.risk_reward,
60601
+ risk: result.result.risk
60602
+ },
60603
+ place
60604
+ });
60605
+ return result;
60606
+ }
60420
60607
  async reduceExistingPosition(payload) {
60421
60608
  const {
60422
60609
  main_account,
package/dist/index.d.ts CHANGED
@@ -128,6 +128,7 @@ export interface PositionsView {
128
128
  price: number;
129
129
  quantity: number;
130
130
  };
131
+ next_risk?: number;
131
132
  }
132
133
  export interface BullishMarket extends RecordModel {
133
134
  id: string;
@@ -777,6 +778,12 @@ export declare class AppDatabase {
777
778
  } | SymbolConfig[]>;
778
779
  unwindSymbolFromDB(symbol: string): Promise<boolean>;
779
780
  hasExistingPosition(symbol: string): Promise<import("pocketbase").RecordModel[]>;
781
+ getPositionWithLowestNextOrder(options: {
782
+ symbol?: string;
783
+ kind: "long" | "short";
784
+ asset?: string;
785
+ exclude?: ExchangeType[];
786
+ }): Promise<PositionsView | null>;
780
787
  hasExistingOrders(symbol: string): Promise<import("pocketbase").RecordModel[]>;
781
788
  removeSymbolFromUnwindingMarkets(symbol: string): Promise<boolean>;
782
789
  removePosition(position: any): Promise<void>;
@@ -1528,6 +1535,33 @@ export declare function getOptimumHedgeFactor(payload: {
1528
1535
  iterations: number;
1529
1536
  converged: boolean;
1530
1537
  };
1538
+ export type CType = {
1539
+ next_order: number;
1540
+ take_profit: number;
1541
+ };
1542
+ export declare function determineCompoundLongTrade(payload: {
1543
+ focus_short_position: CType;
1544
+ focus_long_position: CType;
1545
+ shortConfig: {
1546
+ entry: number;
1547
+ stop: number;
1548
+ risk_reward: number;
1549
+ risk: number;
1550
+ symbol: string;
1551
+ profit_percent: number;
1552
+ };
1553
+ rr?: number;
1554
+ global_config: GlobalConfig;
1555
+ }): {
1556
+ start_risk: number;
1557
+ short_profit: number;
1558
+ support: number;
1559
+ resistance: number;
1560
+ long_v: any;
1561
+ profit_percent: number;
1562
+ result: any;
1563
+ short_max_size: any;
1564
+ };
1531
1565
  declare class ExchangePosition {
1532
1566
  exchange: BaseExchange;
1533
1567
  exchange_account: ExchangeAccount$1;
@@ -2015,6 +2049,32 @@ declare class ExchangeAccount$1 {
2015
2049
  symbol: string;
2016
2050
  kind: "long" | "short";
2017
2051
  }): Promise<number>;
2052
+ /**
2053
+ * Updates the risk configuration for an empty position using the next_risk value.
2054
+ * This implements progressive risk management where successful trades increase future risk tolerance.
2055
+ *
2056
+ * @param payload.symbol - The trading symbol (e.g., "BTCUSDT")
2057
+ * @param payload.kind - Position type: "long" or "short"
2058
+ * @returns Object indicating if update was successful with old/new risk values
2059
+ */
2060
+ updateRiskOnEmpty(payload: {
2061
+ symbol: string;
2062
+ kind: "long" | "short";
2063
+ }): Promise<{
2064
+ updated: boolean;
2065
+ symbol: string;
2066
+ kind: "long" | "short";
2067
+ old_risk: number;
2068
+ new_risk: number;
2069
+ reason?: undefined;
2070
+ } | {
2071
+ updated: boolean;
2072
+ symbol: string;
2073
+ kind: "long" | "short";
2074
+ reason: string;
2075
+ old_risk?: undefined;
2076
+ new_risk?: undefined;
2077
+ }>;
2018
2078
  updateGoodHedgeConfig(payload: {
2019
2079
  symbol: string;
2020
2080
  params?: {
@@ -2336,6 +2396,18 @@ declare class ExchangeAccount$1 {
2336
2396
  price_places: string;
2337
2397
  decimal_places: string;
2338
2398
  }>;
2399
+ placeCompoundShortTrade(payload: {}): Promise<void>;
2400
+ placeCompoundLongTrade(payload: {
2401
+ symbol: string;
2402
+ params: {
2403
+ resistance: number;
2404
+ support: number;
2405
+ profit_percent: number;
2406
+ risk_reward: number;
2407
+ risk: number;
2408
+ };
2409
+ place?: boolean;
2410
+ }): Promise<void>;
2339
2411
  }
2340
2412
  declare function getExchangeAccount(payload: {
2341
2413
  account: ExchangeType;
@@ -2530,6 +2602,25 @@ declare class App {
2530
2602
  pnl: number;
2531
2603
  };
2532
2604
  }>;
2605
+ compoundLongTrade(payload: {
2606
+ main_account: ExchangeType & {
2607
+ symbol: string;
2608
+ };
2609
+ focus_account: ExchangeType & {
2610
+ symbol: string;
2611
+ };
2612
+ place?: boolean;
2613
+ rr?: number;
2614
+ }): Promise<{
2615
+ start_risk: number;
2616
+ short_profit: number;
2617
+ support: number;
2618
+ resistance: number;
2619
+ long_v: any;
2620
+ profit_percent: number;
2621
+ result: any;
2622
+ short_max_size: any;
2623
+ }>;
2533
2624
  reduceExistingPosition(payload: {
2534
2625
  main_account: ExchangeType & {
2535
2626
  symbol: string;
package/dist/index.js CHANGED
@@ -52433,6 +52433,37 @@ class AppDatabase {
52433
52433
  });
52434
52434
  return result;
52435
52435
  }
52436
+ async getPositionWithLowestNextOrder(options) {
52437
+ const { symbol, kind, asset, exclude } = options;
52438
+ try {
52439
+ let filter = `kind="${kind}" && next_order != null`;
52440
+ if (asset) {
52441
+ filter += ` && symbol ~ "${asset.toUpperCase()}%"`;
52442
+ } else if (symbol) {
52443
+ filter += ` && symbol:lower="${symbol.toLowerCase()}"`;
52444
+ } else {
52445
+ throw new Error("Either symbol or asset must be provided");
52446
+ }
52447
+ if (exclude && exclude.length > 0) {
52448
+ const excludeConditions = exclude.map((acc) => `(p_account.owner:lower != "${acc.owner.toLowerCase()}" || p_account.exchange:lower != "${acc.exchange.toLowerCase()}")`).join(" && ");
52449
+ filter += ` && (${excludeConditions})`;
52450
+ }
52451
+ const sortDirection = kind === "short" ? "+" : "-";
52452
+ const positions = await this.pb.collection("positions_view").getList(1, 1, {
52453
+ filter,
52454
+ sort: `${sortDirection}next_order`,
52455
+ expand: "p_account"
52456
+ });
52457
+ if (positions.items.length > 0) {
52458
+ return positions.items[0];
52459
+ }
52460
+ return null;
52461
+ } catch (error) {
52462
+ const identifier = asset ? `asset ${asset}` : `symbol ${symbol}`;
52463
+ console.error(`Error fetching position with ${kind === "short" ? "lowest" : "highest"} next_order for ${identifier} ${kind}:`, error);
52464
+ return null;
52465
+ }
52466
+ }
52436
52467
  async hasExistingOrders(symbol) {
52437
52468
  const result = await this.pb.collection("orders").getFullList({
52438
52469
  filter: `symbol:lower="${symbol.toLowerCase()}"`
@@ -54386,6 +54417,52 @@ function getOptimumHedgeFactor(payload) {
54386
54417
  converged: best_diff <= tolerance
54387
54418
  };
54388
54419
  }
54420
+ function determineCompoundLongTrade(payload) {
54421
+ const {
54422
+ focus_short_position,
54423
+ focus_long_position,
54424
+ shortConfig,
54425
+ global_config,
54426
+ rr = 1
54427
+ } = payload;
54428
+ const short_app_config = buildAppConfig(global_config, {
54429
+ entry: shortConfig.entry,
54430
+ stop: shortConfig.stop,
54431
+ risk_reward: shortConfig.risk_reward,
54432
+ risk: shortConfig.risk,
54433
+ symbol: shortConfig.symbol
54434
+ });
54435
+ const short_max_size = short_app_config.last_value.avg_size;
54436
+ const start_risk = Math.abs(short_app_config.last_value.neg_pnl) * rr;
54437
+ const short_profit = short_app_config.last_value.avg_size * short_app_config.last_value.avg_entry * shortConfig.profit_percent / 100;
54438
+ const support = Math.abs(short_app_config.last_value.avg_entry - short_profit) * rr;
54439
+ const resistance = focus_short_position.next_order || focus_long_position.take_profit;
54440
+ const result = getRiskReward({
54441
+ entry: resistance,
54442
+ stop: support,
54443
+ risk: start_risk,
54444
+ global_config,
54445
+ force_exact_risk: true
54446
+ });
54447
+ const long_app_config = buildAppConfig(global_config, {
54448
+ entry: resistance,
54449
+ stop: support,
54450
+ risk_reward: result.risk_reward,
54451
+ risk: result.risk,
54452
+ symbol: shortConfig.symbol
54453
+ });
54454
+ const long_profit_percent = start_risk * 2 * 100 / (long_app_config.last_value.avg_size * long_app_config.last_value.avg_entry);
54455
+ return {
54456
+ start_risk,
54457
+ short_profit,
54458
+ support: to_f2(support, global_config.price_places),
54459
+ resistance: to_f2(resistance, global_config.price_places),
54460
+ long_v: long_app_config.last_value,
54461
+ profit_percent: to_f2(long_profit_percent, "%.3f"),
54462
+ result,
54463
+ short_max_size
54464
+ };
54465
+ }
54389
54466
 
54390
54467
  // src/helpers/strategy.ts
54391
54468
  class Strategy {
@@ -58469,6 +58546,10 @@ class ExchangeAccount {
58469
58546
  symbol,
58470
58547
  kind
58471
58548
  });
58549
+ await this.updateRiskOnEmpty({
58550
+ symbol,
58551
+ kind
58552
+ });
58472
58553
  }
58473
58554
  const long_config = await this.getPositionConfig({
58474
58555
  symbol,
@@ -58960,17 +59041,53 @@ class ExchangeAccount {
58960
59041
  if (position2?.expand?.config) {
58961
59042
  const config2 = position2.expand.config;
58962
59043
  let _profit = config2.profit;
59044
+ let risk = config2.risk;
59045
+ let next_risk = position2.next_risk;
58963
59046
  let _profit_percent = config2?.profit_percent;
58964
59047
  if (_profit_percent && (position2?.quantity || 0) > 0) {
58965
59048
  _profit = to_f2(position2.quantity * _profit_percent * position2.entry / 100);
59049
+ next_risk = risk + _profit;
58966
59050
  }
58967
59051
  await this.app_db.update_db_position(position2, {
58968
- target_pnl: _profit
59052
+ target_pnl: _profit,
59053
+ next_risk
58969
59054
  });
58970
59055
  return _profit;
58971
59056
  }
58972
59057
  return 0;
58973
59058
  }
59059
+ async updateRiskOnEmpty(payload) {
59060
+ const { symbol, kind } = payload;
59061
+ const position2 = await this.syncAccount({
59062
+ symbol,
59063
+ kind
59064
+ });
59065
+ if (position2 && position2.quantity === 0) {
59066
+ if (position2.next_risk && position2.next_risk > 0) {
59067
+ await this.getPositionConfig({
59068
+ symbol,
59069
+ kind,
59070
+ params: {
59071
+ risk: position2.next_risk
59072
+ }
59073
+ });
59074
+ console.log(`Updated ${kind} position config for ${symbol}: risk = ${position2.next_risk}`);
59075
+ return {
59076
+ updated: true,
59077
+ symbol,
59078
+ kind,
59079
+ old_risk: position2.expand?.config?.risk,
59080
+ new_risk: position2.next_risk
59081
+ };
59082
+ }
59083
+ }
59084
+ return {
59085
+ updated: false,
59086
+ symbol,
59087
+ kind,
59088
+ reason: position2 ? position2.quantity > 0 ? "Position not empty" : "No next_risk available" : "Position not found"
59089
+ };
59090
+ }
58974
59091
  async updateGoodHedgeConfig(payload) {
58975
59092
  const {
58976
59093
  params,
@@ -60026,6 +60143,38 @@ class ExchangeAccount {
60026
60143
  decimal_places: symbol_config.decimal_places
60027
60144
  });
60028
60145
  }
60146
+ async placeCompoundShortTrade(payload) {
60147
+ }
60148
+ async placeCompoundLongTrade(payload) {
60149
+ const { symbol, params, place = false } = payload;
60150
+ if (place) {
60151
+ await this.getPositionConfig({
60152
+ symbol,
60153
+ kind: "long",
60154
+ params: {
60155
+ entry: params.resistance,
60156
+ stop: params.support,
60157
+ risk_reward: params.risk_reward,
60158
+ risk: params.risk,
60159
+ profit_percent: params.profit_percent
60160
+ }
60161
+ });
60162
+ const short_position = await this.syncAccount({
60163
+ symbol,
60164
+ kind: "short",
60165
+ as_view: true
60166
+ });
60167
+ if (short_position.quantity >= short_position.avg_qty) {
60168
+ await this.placeTrade({
60169
+ symbol,
60170
+ kind: "long",
60171
+ ignore_config: true,
60172
+ limit: true,
60173
+ place: true
60174
+ });
60175
+ }
60176
+ }
60177
+ }
60029
60178
  }
60030
60179
  function getExchangeKlass(exchange) {
60031
60180
  const func = exchange === "binance" ? BinanceExchange : BybitExchange;
@@ -60366,6 +60515,43 @@ class App {
60366
60515
  });
60367
60516
  return result;
60368
60517
  }
60518
+ async compoundLongTrade(payload) {
60519
+ const { main_account, focus_account, rr, place } = payload;
60520
+ const main_exchange_account = await this.getExchangeAccount(main_account);
60521
+ const focus_exchange_account = await this.getExchangeAccount(focus_account);
60522
+ const focus_position = await focus_exchange_account.syncAccount({
60523
+ symbol: focus_account.symbol,
60524
+ as_view: true
60525
+ });
60526
+ const focus_long_position = focus_position.find((k) => k.kind === "long");
60527
+ const focus_short_position = focus_position.find((k) => k.kind === "short");
60528
+ const shortConfig = await main_exchange_account.getPositionConfig({
60529
+ symbol: main_account.symbol,
60530
+ kind: "short"
60531
+ });
60532
+ const symbol_config = await focus_exchange_account.recomputeSymbolConfig({
60533
+ symbol: focus_account.symbol
60534
+ });
60535
+ const result = determineCompoundLongTrade({
60536
+ focus_short_position,
60537
+ focus_long_position,
60538
+ shortConfig,
60539
+ global_config: symbol_config,
60540
+ rr
60541
+ });
60542
+ await main_exchange_account.placeCompoundLongTrade({
60543
+ symbol: main_account.symbol,
60544
+ params: {
60545
+ resistance: result.resistance,
60546
+ support: result.support,
60547
+ profit_percent: result.profit_percent,
60548
+ risk_reward: result.result.risk_reward,
60549
+ risk: result.result.risk
60550
+ },
60551
+ place
60552
+ });
60553
+ return result;
60554
+ }
60369
60555
  async reduceExistingPosition(payload) {
60370
60556
  const {
60371
60557
  main_account,
@@ -60507,6 +60693,7 @@ export {
60507
60693
  determineRewardFactor,
60508
60694
  determineOptimumRisk,
60509
60695
  determineOptimumReward,
60696
+ determineCompoundLongTrade,
60510
60697
  exports_database as database,
60511
60698
  createArray,
60512
60699
  computeRiskReward,
@@ -59187,6 +59187,37 @@ class AppDatabase {
59187
59187
  });
59188
59188
  return result;
59189
59189
  }
59190
+ async getPositionWithLowestNextOrder(options) {
59191
+ const { symbol, kind, asset, exclude } = options;
59192
+ try {
59193
+ let filter = `kind="${kind}" && next_order != null`;
59194
+ if (asset) {
59195
+ filter += ` && symbol ~ "${asset.toUpperCase()}%"`;
59196
+ } else if (symbol) {
59197
+ filter += ` && symbol:lower="${symbol.toLowerCase()}"`;
59198
+ } else {
59199
+ throw new Error("Either symbol or asset must be provided");
59200
+ }
59201
+ if (exclude && exclude.length > 0) {
59202
+ const excludeConditions = exclude.map((acc) => `(p_account.owner:lower != "${acc.owner.toLowerCase()}" || p_account.exchange:lower != "${acc.exchange.toLowerCase()}")`).join(" && ");
59203
+ filter += ` && (${excludeConditions})`;
59204
+ }
59205
+ const sortDirection = kind === "short" ? "+" : "-";
59206
+ const positions = await this.pb.collection("positions_view").getList(1, 1, {
59207
+ filter,
59208
+ sort: `${sortDirection}next_order`,
59209
+ expand: "p_account"
59210
+ });
59211
+ if (positions.items.length > 0) {
59212
+ return positions.items[0];
59213
+ }
59214
+ return null;
59215
+ } catch (error) {
59216
+ const identifier = asset ? `asset ${asset}` : `symbol ${symbol}`;
59217
+ console.error(`Error fetching position with ${kind === "short" ? "lowest" : "highest"} next_order for ${identifier} ${kind}:`, error);
59218
+ return null;
59219
+ }
59220
+ }
59190
59221
  async hasExistingOrders(symbol) {
59191
59222
  const result = await this.pb.collection("orders").getFullList({
59192
59223
  filter: `symbol:lower="${symbol.toLowerCase()}"`
@@ -61114,6 +61145,52 @@ function getOptimumHedgeFactor(payload) {
61114
61145
  converged: best_diff <= tolerance
61115
61146
  };
61116
61147
  }
61148
+ function determineCompoundLongTrade(payload) {
61149
+ const {
61150
+ focus_short_position,
61151
+ focus_long_position,
61152
+ shortConfig,
61153
+ global_config,
61154
+ rr = 1
61155
+ } = payload;
61156
+ const short_app_config = buildAppConfig(global_config, {
61157
+ entry: shortConfig.entry,
61158
+ stop: shortConfig.stop,
61159
+ risk_reward: shortConfig.risk_reward,
61160
+ risk: shortConfig.risk,
61161
+ symbol: shortConfig.symbol
61162
+ });
61163
+ const short_max_size = short_app_config.last_value.avg_size;
61164
+ const start_risk = Math.abs(short_app_config.last_value.neg_pnl) * rr;
61165
+ const short_profit = short_app_config.last_value.avg_size * short_app_config.last_value.avg_entry * shortConfig.profit_percent / 100;
61166
+ const support = Math.abs(short_app_config.last_value.avg_entry - short_profit) * rr;
61167
+ const resistance = focus_short_position.next_order || focus_long_position.take_profit;
61168
+ const result = getRiskReward({
61169
+ entry: resistance,
61170
+ stop: support,
61171
+ risk: start_risk,
61172
+ global_config,
61173
+ force_exact_risk: true
61174
+ });
61175
+ const long_app_config = buildAppConfig(global_config, {
61176
+ entry: resistance,
61177
+ stop: support,
61178
+ risk_reward: result.risk_reward,
61179
+ risk: result.risk,
61180
+ symbol: shortConfig.symbol
61181
+ });
61182
+ const long_profit_percent = start_risk * 2 * 100 / (long_app_config.last_value.avg_size * long_app_config.last_value.avg_entry);
61183
+ return {
61184
+ start_risk,
61185
+ short_profit,
61186
+ support: to_f2(support, global_config.price_places),
61187
+ resistance: to_f2(resistance, global_config.price_places),
61188
+ long_v: long_app_config.last_value,
61189
+ profit_percent: to_f2(long_profit_percent, "%.3f"),
61190
+ result,
61191
+ short_max_size
61192
+ };
61193
+ }
61117
61194
 
61118
61195
  // src/helpers/strategy.ts
61119
61196
  class Strategy {
@@ -65197,6 +65274,10 @@ class ExchangeAccount {
65197
65274
  symbol,
65198
65275
  kind
65199
65276
  });
65277
+ await this.updateRiskOnEmpty({
65278
+ symbol,
65279
+ kind
65280
+ });
65200
65281
  }
65201
65282
  const long_config = await this.getPositionConfig({
65202
65283
  symbol,
@@ -65688,17 +65769,53 @@ class ExchangeAccount {
65688
65769
  if (position2?.expand?.config) {
65689
65770
  const config2 = position2.expand.config;
65690
65771
  let _profit = config2.profit;
65772
+ let risk = config2.risk;
65773
+ let next_risk = position2.next_risk;
65691
65774
  let _profit_percent = config2?.profit_percent;
65692
65775
  if (_profit_percent && (position2?.quantity || 0) > 0) {
65693
65776
  _profit = to_f2(position2.quantity * _profit_percent * position2.entry / 100);
65777
+ next_risk = risk + _profit;
65694
65778
  }
65695
65779
  await this.app_db.update_db_position(position2, {
65696
- target_pnl: _profit
65780
+ target_pnl: _profit,
65781
+ next_risk
65697
65782
  });
65698
65783
  return _profit;
65699
65784
  }
65700
65785
  return 0;
65701
65786
  }
65787
+ async updateRiskOnEmpty(payload) {
65788
+ const { symbol, kind } = payload;
65789
+ const position2 = await this.syncAccount({
65790
+ symbol,
65791
+ kind
65792
+ });
65793
+ if (position2 && position2.quantity === 0) {
65794
+ if (position2.next_risk && position2.next_risk > 0) {
65795
+ await this.getPositionConfig({
65796
+ symbol,
65797
+ kind,
65798
+ params: {
65799
+ risk: position2.next_risk
65800
+ }
65801
+ });
65802
+ console.log(`Updated ${kind} position config for ${symbol}: risk = ${position2.next_risk}`);
65803
+ return {
65804
+ updated: true,
65805
+ symbol,
65806
+ kind,
65807
+ old_risk: position2.expand?.config?.risk,
65808
+ new_risk: position2.next_risk
65809
+ };
65810
+ }
65811
+ }
65812
+ return {
65813
+ updated: false,
65814
+ symbol,
65815
+ kind,
65816
+ reason: position2 ? position2.quantity > 0 ? "Position not empty" : "No next_risk available" : "Position not found"
65817
+ };
65818
+ }
65702
65819
  async updateGoodHedgeConfig(payload) {
65703
65820
  const {
65704
65821
  params,
@@ -66754,6 +66871,38 @@ class ExchangeAccount {
66754
66871
  decimal_places: symbol_config.decimal_places
66755
66872
  });
66756
66873
  }
66874
+ async placeCompoundShortTrade(payload) {
66875
+ }
66876
+ async placeCompoundLongTrade(payload) {
66877
+ const { symbol, params, place = false } = payload;
66878
+ if (place) {
66879
+ await this.getPositionConfig({
66880
+ symbol,
66881
+ kind: "long",
66882
+ params: {
66883
+ entry: params.resistance,
66884
+ stop: params.support,
66885
+ risk_reward: params.risk_reward,
66886
+ risk: params.risk,
66887
+ profit_percent: params.profit_percent
66888
+ }
66889
+ });
66890
+ const short_position = await this.syncAccount({
66891
+ symbol,
66892
+ kind: "short",
66893
+ as_view: true
66894
+ });
66895
+ if (short_position.quantity >= short_position.avg_qty) {
66896
+ await this.placeTrade({
66897
+ symbol,
66898
+ kind: "long",
66899
+ ignore_config: true,
66900
+ limit: true,
66901
+ place: true
66902
+ });
66903
+ }
66904
+ }
66905
+ }
66757
66906
  }
66758
66907
  function getExchangeKlass(exchange) {
66759
66908
  const func = exchange === "binance" ? BinanceExchange : BybitExchange;
@@ -67094,6 +67243,43 @@ class App {
67094
67243
  });
67095
67244
  return result;
67096
67245
  }
67246
+ async compoundLongTrade(payload) {
67247
+ const { main_account, focus_account, rr, place } = payload;
67248
+ const main_exchange_account = await this.getExchangeAccount(main_account);
67249
+ const focus_exchange_account = await this.getExchangeAccount(focus_account);
67250
+ const focus_position = await focus_exchange_account.syncAccount({
67251
+ symbol: focus_account.symbol,
67252
+ as_view: true
67253
+ });
67254
+ const focus_long_position = focus_position.find((k) => k.kind === "long");
67255
+ const focus_short_position = focus_position.find((k) => k.kind === "short");
67256
+ const shortConfig = await main_exchange_account.getPositionConfig({
67257
+ symbol: main_account.symbol,
67258
+ kind: "short"
67259
+ });
67260
+ const symbol_config = await focus_exchange_account.recomputeSymbolConfig({
67261
+ symbol: focus_account.symbol
67262
+ });
67263
+ const result = determineCompoundLongTrade({
67264
+ focus_short_position,
67265
+ focus_long_position,
67266
+ shortConfig,
67267
+ global_config: symbol_config,
67268
+ rr
67269
+ });
67270
+ await main_exchange_account.placeCompoundLongTrade({
67271
+ symbol: main_account.symbol,
67272
+ params: {
67273
+ resistance: result.resistance,
67274
+ support: result.support,
67275
+ profit_percent: result.profit_percent,
67276
+ risk_reward: result.result.risk_reward,
67277
+ risk: result.result.risk
67278
+ },
67279
+ place
67280
+ });
67281
+ return result;
67282
+ }
67097
67283
  async reduceExistingPosition(payload) {
67098
67284
  const {
67099
67285
  main_account,
@@ -59164,6 +59164,37 @@ class AppDatabase {
59164
59164
  });
59165
59165
  return result;
59166
59166
  }
59167
+ async getPositionWithLowestNextOrder(options) {
59168
+ const { symbol, kind, asset, exclude } = options;
59169
+ try {
59170
+ let filter = `kind="${kind}" && next_order != null`;
59171
+ if (asset) {
59172
+ filter += ` && symbol ~ "${asset.toUpperCase()}%"`;
59173
+ } else if (symbol) {
59174
+ filter += ` && symbol:lower="${symbol.toLowerCase()}"`;
59175
+ } else {
59176
+ throw new Error("Either symbol or asset must be provided");
59177
+ }
59178
+ if (exclude && exclude.length > 0) {
59179
+ const excludeConditions = exclude.map((acc) => `(p_account.owner:lower != "${acc.owner.toLowerCase()}" || p_account.exchange:lower != "${acc.exchange.toLowerCase()}")`).join(" && ");
59180
+ filter += ` && (${excludeConditions})`;
59181
+ }
59182
+ const sortDirection = kind === "short" ? "+" : "-";
59183
+ const positions = await this.pb.collection("positions_view").getList(1, 1, {
59184
+ filter,
59185
+ sort: `${sortDirection}next_order`,
59186
+ expand: "p_account"
59187
+ });
59188
+ if (positions.items.length > 0) {
59189
+ return positions.items[0];
59190
+ }
59191
+ return null;
59192
+ } catch (error) {
59193
+ const identifier = asset ? `asset ${asset}` : `symbol ${symbol}`;
59194
+ console.error(`Error fetching position with ${kind === "short" ? "lowest" : "highest"} next_order for ${identifier} ${kind}:`, error);
59195
+ return null;
59196
+ }
59197
+ }
59167
59198
  async hasExistingOrders(symbol) {
59168
59199
  const result = await this.pb.collection("orders").getFullList({
59169
59200
  filter: `symbol:lower="${symbol.toLowerCase()}"`
@@ -61091,6 +61122,52 @@ function getOptimumHedgeFactor(payload) {
61091
61122
  converged: best_diff <= tolerance
61092
61123
  };
61093
61124
  }
61125
+ function determineCompoundLongTrade(payload) {
61126
+ const {
61127
+ focus_short_position,
61128
+ focus_long_position,
61129
+ shortConfig,
61130
+ global_config,
61131
+ rr = 1
61132
+ } = payload;
61133
+ const short_app_config = buildAppConfig(global_config, {
61134
+ entry: shortConfig.entry,
61135
+ stop: shortConfig.stop,
61136
+ risk_reward: shortConfig.risk_reward,
61137
+ risk: shortConfig.risk,
61138
+ symbol: shortConfig.symbol
61139
+ });
61140
+ const short_max_size = short_app_config.last_value.avg_size;
61141
+ const start_risk = Math.abs(short_app_config.last_value.neg_pnl) * rr;
61142
+ const short_profit = short_app_config.last_value.avg_size * short_app_config.last_value.avg_entry * shortConfig.profit_percent / 100;
61143
+ const support = Math.abs(short_app_config.last_value.avg_entry - short_profit) * rr;
61144
+ const resistance = focus_short_position.next_order || focus_long_position.take_profit;
61145
+ const result = getRiskReward({
61146
+ entry: resistance,
61147
+ stop: support,
61148
+ risk: start_risk,
61149
+ global_config,
61150
+ force_exact_risk: true
61151
+ });
61152
+ const long_app_config = buildAppConfig(global_config, {
61153
+ entry: resistance,
61154
+ stop: support,
61155
+ risk_reward: result.risk_reward,
61156
+ risk: result.risk,
61157
+ symbol: shortConfig.symbol
61158
+ });
61159
+ const long_profit_percent = start_risk * 2 * 100 / (long_app_config.last_value.avg_size * long_app_config.last_value.avg_entry);
61160
+ return {
61161
+ start_risk,
61162
+ short_profit,
61163
+ support: to_f2(support, global_config.price_places),
61164
+ resistance: to_f2(resistance, global_config.price_places),
61165
+ long_v: long_app_config.last_value,
61166
+ profit_percent: to_f2(long_profit_percent, "%.3f"),
61167
+ result,
61168
+ short_max_size
61169
+ };
61170
+ }
61094
61171
 
61095
61172
  // src/helpers/strategy.ts
61096
61173
  class Strategy {
@@ -65174,6 +65251,10 @@ class ExchangeAccount {
65174
65251
  symbol,
65175
65252
  kind
65176
65253
  });
65254
+ await this.updateRiskOnEmpty({
65255
+ symbol,
65256
+ kind
65257
+ });
65177
65258
  }
65178
65259
  const long_config = await this.getPositionConfig({
65179
65260
  symbol,
@@ -65665,17 +65746,53 @@ class ExchangeAccount {
65665
65746
  if (position2?.expand?.config) {
65666
65747
  const config2 = position2.expand.config;
65667
65748
  let _profit = config2.profit;
65749
+ let risk = config2.risk;
65750
+ let next_risk = position2.next_risk;
65668
65751
  let _profit_percent = config2?.profit_percent;
65669
65752
  if (_profit_percent && (position2?.quantity || 0) > 0) {
65670
65753
  _profit = to_f2(position2.quantity * _profit_percent * position2.entry / 100);
65754
+ next_risk = risk + _profit;
65671
65755
  }
65672
65756
  await this.app_db.update_db_position(position2, {
65673
- target_pnl: _profit
65757
+ target_pnl: _profit,
65758
+ next_risk
65674
65759
  });
65675
65760
  return _profit;
65676
65761
  }
65677
65762
  return 0;
65678
65763
  }
65764
+ async updateRiskOnEmpty(payload) {
65765
+ const { symbol, kind } = payload;
65766
+ const position2 = await this.syncAccount({
65767
+ symbol,
65768
+ kind
65769
+ });
65770
+ if (position2 && position2.quantity === 0) {
65771
+ if (position2.next_risk && position2.next_risk > 0) {
65772
+ await this.getPositionConfig({
65773
+ symbol,
65774
+ kind,
65775
+ params: {
65776
+ risk: position2.next_risk
65777
+ }
65778
+ });
65779
+ console.log(`Updated ${kind} position config for ${symbol}: risk = ${position2.next_risk}`);
65780
+ return {
65781
+ updated: true,
65782
+ symbol,
65783
+ kind,
65784
+ old_risk: position2.expand?.config?.risk,
65785
+ new_risk: position2.next_risk
65786
+ };
65787
+ }
65788
+ }
65789
+ return {
65790
+ updated: false,
65791
+ symbol,
65792
+ kind,
65793
+ reason: position2 ? position2.quantity > 0 ? "Position not empty" : "No next_risk available" : "Position not found"
65794
+ };
65795
+ }
65679
65796
  async updateGoodHedgeConfig(payload) {
65680
65797
  const {
65681
65798
  params,
@@ -66731,6 +66848,38 @@ class ExchangeAccount {
66731
66848
  decimal_places: symbol_config.decimal_places
66732
66849
  });
66733
66850
  }
66851
+ async placeCompoundShortTrade(payload) {
66852
+ }
66853
+ async placeCompoundLongTrade(payload) {
66854
+ const { symbol, params, place = false } = payload;
66855
+ if (place) {
66856
+ await this.getPositionConfig({
66857
+ symbol,
66858
+ kind: "long",
66859
+ params: {
66860
+ entry: params.resistance,
66861
+ stop: params.support,
66862
+ risk_reward: params.risk_reward,
66863
+ risk: params.risk,
66864
+ profit_percent: params.profit_percent
66865
+ }
66866
+ });
66867
+ const short_position = await this.syncAccount({
66868
+ symbol,
66869
+ kind: "short",
66870
+ as_view: true
66871
+ });
66872
+ if (short_position.quantity >= short_position.avg_qty) {
66873
+ await this.placeTrade({
66874
+ symbol,
66875
+ kind: "long",
66876
+ ignore_config: true,
66877
+ limit: true,
66878
+ place: true
66879
+ });
66880
+ }
66881
+ }
66882
+ }
66734
66883
  }
66735
66884
  function getExchangeKlass(exchange) {
66736
66885
  const func = exchange === "binance" ? BinanceExchange : BybitExchange;
@@ -67071,6 +67220,43 @@ class App {
67071
67220
  });
67072
67221
  return result;
67073
67222
  }
67223
+ async compoundLongTrade(payload) {
67224
+ const { main_account, focus_account, rr, place } = payload;
67225
+ const main_exchange_account = await this.getExchangeAccount(main_account);
67226
+ const focus_exchange_account = await this.getExchangeAccount(focus_account);
67227
+ const focus_position = await focus_exchange_account.syncAccount({
67228
+ symbol: focus_account.symbol,
67229
+ as_view: true
67230
+ });
67231
+ const focus_long_position = focus_position.find((k) => k.kind === "long");
67232
+ const focus_short_position = focus_position.find((k) => k.kind === "short");
67233
+ const shortConfig = await main_exchange_account.getPositionConfig({
67234
+ symbol: main_account.symbol,
67235
+ kind: "short"
67236
+ });
67237
+ const symbol_config = await focus_exchange_account.recomputeSymbolConfig({
67238
+ symbol: focus_account.symbol
67239
+ });
67240
+ const result = determineCompoundLongTrade({
67241
+ focus_short_position,
67242
+ focus_long_position,
67243
+ shortConfig,
67244
+ global_config: symbol_config,
67245
+ rr
67246
+ });
67247
+ await main_exchange_account.placeCompoundLongTrade({
67248
+ symbol: main_account.symbol,
67249
+ params: {
67250
+ resistance: result.resistance,
67251
+ support: result.support,
67252
+ profit_percent: result.profit_percent,
67253
+ risk_reward: result.result.risk_reward,
67254
+ risk: result.result.risk
67255
+ },
67256
+ place
67257
+ });
67258
+ return result;
67259
+ }
67074
67260
  async reduceExistingPosition(payload) {
67075
67261
  const {
67076
67262
  main_account,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gbozee/ultimate",
3
3
  "type": "module",
4
- "version": "0.0.2-130",
4
+ "version": "0.0.2-131",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -35,6 +35,7 @@
35
35
  "build": "bun run build.ts",
36
36
  "prepublishOnly": "bun run build",
37
37
  "test": "bun test --timeout 300000 test",
38
+ "test:unit": "bun test --timeout 300000 tests/unit-tests",
38
39
  "mcp:client": "bun run tests/mcp-client.js dist/mcp-server.js",
39
40
  "npm:publish": "npm publish --access public --registry=https://registry.npmjs.org/"
40
41
  },