@gbozee/ultimate 0.0.2-130 → 0.0.2-132

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,54 @@ 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 diff = short_profit * rr / short_app_config.last_value.avg_size;
2154
+ const support = Math.abs(short_app_config.last_value.avg_entry - diff);
2155
+ const resistance = focus_short_position.next_order || focus_long_position.take_profit;
2156
+ console.log({ support, resistance, short_profit });
2157
+ const result = getRiskReward({
2158
+ entry: resistance,
2159
+ stop: support,
2160
+ risk: start_risk,
2161
+ global_config,
2162
+ force_exact_risk: true
2163
+ });
2164
+ const long_app_config = buildAppConfig(global_config, {
2165
+ entry: resistance,
2166
+ stop: support,
2167
+ risk_reward: result.risk_reward,
2168
+ risk: result.risk,
2169
+ symbol: shortConfig.symbol
2170
+ });
2171
+ const long_profit_percent = start_risk * 2 * 100 / (long_app_config.last_value.avg_size * long_app_config.last_value.avg_entry);
2172
+ return {
2173
+ start_risk,
2174
+ short_profit,
2175
+ support: to_f(support, global_config.price_places),
2176
+ resistance: to_f(resistance, global_config.price_places),
2177
+ long_v: long_app_config.last_value,
2178
+ profit_percent: to_f(long_profit_percent, "%.3f"),
2179
+ result,
2180
+ short_max_size
2181
+ };
2182
+ }
2135
2183
  // src/helpers/strategy.ts
2136
2184
  class Strategy {
2137
2185
  position;
@@ -2665,6 +2713,7 @@ export {
2665
2713
  determineRewardFactor,
2666
2714
  determineOptimumRisk,
2667
2715
  determineOptimumReward,
2716
+ determineCompoundLongTrade,
2668
2717
  createGapPairs,
2669
2718
  createArray,
2670
2719
  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,54 @@ 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 diff = short_profit * rr / short_app_config.last_value.avg_size;
54491
+ const support = Math.abs(short_app_config.last_value.avg_entry - diff);
54492
+ const resistance = focus_short_position.next_order || focus_long_position.take_profit;
54493
+ console.log({ support, resistance, short_profit });
54494
+ const result = getRiskReward({
54495
+ entry: resistance,
54496
+ stop: support,
54497
+ risk: start_risk,
54498
+ global_config,
54499
+ force_exact_risk: true
54500
+ });
54501
+ const long_app_config = buildAppConfig(global_config, {
54502
+ entry: resistance,
54503
+ stop: support,
54504
+ risk_reward: result.risk_reward,
54505
+ risk: result.risk,
54506
+ symbol: shortConfig.symbol
54507
+ });
54508
+ const long_profit_percent = start_risk * 2 * 100 / (long_app_config.last_value.avg_size * long_app_config.last_value.avg_entry);
54509
+ return {
54510
+ start_risk,
54511
+ short_profit,
54512
+ support: to_f2(support, global_config.price_places),
54513
+ resistance: to_f2(resistance, global_config.price_places),
54514
+ long_v: long_app_config.last_value,
54515
+ profit_percent: to_f2(long_profit_percent, "%.3f"),
54516
+ result,
54517
+ short_max_size
54518
+ };
54519
+ }
54440
54520
 
54441
54521
  // src/helpers/strategy.ts
54442
54522
  class Strategy {
@@ -58520,6 +58600,10 @@ class ExchangeAccount {
58520
58600
  symbol,
58521
58601
  kind
58522
58602
  });
58603
+ await this.updateRiskOnEmpty({
58604
+ symbol,
58605
+ kind
58606
+ });
58523
58607
  }
58524
58608
  const long_config = await this.getPositionConfig({
58525
58609
  symbol,
@@ -59011,17 +59095,53 @@ class ExchangeAccount {
59011
59095
  if (position2?.expand?.config) {
59012
59096
  const config2 = position2.expand.config;
59013
59097
  let _profit = config2.profit;
59098
+ let risk = config2.risk;
59099
+ let next_risk = position2.next_risk;
59014
59100
  let _profit_percent = config2?.profit_percent;
59015
59101
  if (_profit_percent && (position2?.quantity || 0) > 0) {
59016
59102
  _profit = to_f2(position2.quantity * _profit_percent * position2.entry / 100);
59103
+ next_risk = risk + _profit;
59017
59104
  }
59018
59105
  await this.app_db.update_db_position(position2, {
59019
- target_pnl: _profit
59106
+ target_pnl: _profit,
59107
+ next_risk
59020
59108
  });
59021
59109
  return _profit;
59022
59110
  }
59023
59111
  return 0;
59024
59112
  }
59113
+ async updateRiskOnEmpty(payload) {
59114
+ const { symbol, kind } = payload;
59115
+ const position2 = await this.syncAccount({
59116
+ symbol,
59117
+ kind
59118
+ });
59119
+ if (position2 && position2.quantity === 0) {
59120
+ if (position2.next_risk && position2.next_risk > 0) {
59121
+ await this.getPositionConfig({
59122
+ symbol,
59123
+ kind,
59124
+ params: {
59125
+ risk: position2.next_risk
59126
+ }
59127
+ });
59128
+ console.log(`Updated ${kind} position config for ${symbol}: risk = ${position2.next_risk}`);
59129
+ return {
59130
+ updated: true,
59131
+ symbol,
59132
+ kind,
59133
+ old_risk: position2.expand?.config?.risk,
59134
+ new_risk: position2.next_risk
59135
+ };
59136
+ }
59137
+ }
59138
+ return {
59139
+ updated: false,
59140
+ symbol,
59141
+ kind,
59142
+ reason: position2 ? position2.quantity > 0 ? "Position not empty" : "No next_risk available" : "Position not found"
59143
+ };
59144
+ }
59025
59145
  async updateGoodHedgeConfig(payload) {
59026
59146
  const {
59027
59147
  params,
@@ -60077,6 +60197,38 @@ class ExchangeAccount {
60077
60197
  decimal_places: symbol_config.decimal_places
60078
60198
  });
60079
60199
  }
60200
+ async placeCompoundShortTrade(payload) {
60201
+ }
60202
+ async placeCompoundLongTrade(payload) {
60203
+ const { symbol, params, place = false } = payload;
60204
+ if (place) {
60205
+ await this.getPositionConfig({
60206
+ symbol,
60207
+ kind: "long",
60208
+ params: {
60209
+ entry: params.resistance,
60210
+ stop: params.support,
60211
+ risk_reward: params.risk_reward,
60212
+ risk: params.risk,
60213
+ profit_percent: params.profit_percent
60214
+ }
60215
+ });
60216
+ const short_position = await this.syncAccount({
60217
+ symbol,
60218
+ kind: "short",
60219
+ as_view: true
60220
+ });
60221
+ if (short_position.quantity >= short_position.avg_qty) {
60222
+ await this.placeTrade({
60223
+ symbol,
60224
+ kind: "long",
60225
+ ignore_config: true,
60226
+ limit: true,
60227
+ place: true
60228
+ });
60229
+ }
60230
+ }
60231
+ }
60080
60232
  }
60081
60233
  function getExchangeKlass(exchange) {
60082
60234
  const func = exchange === "binance" ? BinanceExchange : BybitExchange;
@@ -60417,6 +60569,43 @@ class App {
60417
60569
  });
60418
60570
  return result;
60419
60571
  }
60572
+ async compoundLongTrade(payload) {
60573
+ const { main_account, focus_account, rr, place } = payload;
60574
+ const main_exchange_account = await this.getExchangeAccount(main_account);
60575
+ const focus_exchange_account = await this.getExchangeAccount(focus_account);
60576
+ const focus_position = await focus_exchange_account.syncAccount({
60577
+ symbol: focus_account.symbol,
60578
+ as_view: true
60579
+ });
60580
+ const focus_long_position = focus_position.find((k) => k.kind === "long");
60581
+ const focus_short_position = focus_position.find((k) => k.kind === "short");
60582
+ const shortConfig = await main_exchange_account.getPositionConfig({
60583
+ symbol: main_account.symbol,
60584
+ kind: "short"
60585
+ });
60586
+ const symbol_config = await focus_exchange_account.recomputeSymbolConfig({
60587
+ symbol: focus_account.symbol
60588
+ });
60589
+ const result = determineCompoundLongTrade({
60590
+ focus_short_position,
60591
+ focus_long_position,
60592
+ shortConfig,
60593
+ global_config: symbol_config,
60594
+ rr
60595
+ });
60596
+ await main_exchange_account.placeCompoundLongTrade({
60597
+ symbol: main_account.symbol,
60598
+ params: {
60599
+ resistance: result.resistance,
60600
+ support: result.support,
60601
+ profit_percent: result.profit_percent,
60602
+ risk_reward: result.result.risk_reward,
60603
+ risk: result.result.risk
60604
+ },
60605
+ place
60606
+ });
60607
+ return result;
60608
+ }
60420
60609
  async reduceExistingPosition(payload) {
60421
60610
  const {
60422
60611
  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,54 @@ 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 diff = short_profit * rr / short_app_config.last_value.avg_size;
54439
+ const support = Math.abs(short_app_config.last_value.avg_entry - diff);
54440
+ const resistance = focus_short_position.next_order || focus_long_position.take_profit;
54441
+ console.log({ support, resistance, short_profit });
54442
+ const result = getRiskReward({
54443
+ entry: resistance,
54444
+ stop: support,
54445
+ risk: start_risk,
54446
+ global_config,
54447
+ force_exact_risk: true
54448
+ });
54449
+ const long_app_config = buildAppConfig(global_config, {
54450
+ entry: resistance,
54451
+ stop: support,
54452
+ risk_reward: result.risk_reward,
54453
+ risk: result.risk,
54454
+ symbol: shortConfig.symbol
54455
+ });
54456
+ const long_profit_percent = start_risk * 2 * 100 / (long_app_config.last_value.avg_size * long_app_config.last_value.avg_entry);
54457
+ return {
54458
+ start_risk,
54459
+ short_profit,
54460
+ support: to_f2(support, global_config.price_places),
54461
+ resistance: to_f2(resistance, global_config.price_places),
54462
+ long_v: long_app_config.last_value,
54463
+ profit_percent: to_f2(long_profit_percent, "%.3f"),
54464
+ result,
54465
+ short_max_size
54466
+ };
54467
+ }
54389
54468
 
54390
54469
  // src/helpers/strategy.ts
54391
54470
  class Strategy {
@@ -58469,6 +58548,10 @@ class ExchangeAccount {
58469
58548
  symbol,
58470
58549
  kind
58471
58550
  });
58551
+ await this.updateRiskOnEmpty({
58552
+ symbol,
58553
+ kind
58554
+ });
58472
58555
  }
58473
58556
  const long_config = await this.getPositionConfig({
58474
58557
  symbol,
@@ -58960,17 +59043,53 @@ class ExchangeAccount {
58960
59043
  if (position2?.expand?.config) {
58961
59044
  const config2 = position2.expand.config;
58962
59045
  let _profit = config2.profit;
59046
+ let risk = config2.risk;
59047
+ let next_risk = position2.next_risk;
58963
59048
  let _profit_percent = config2?.profit_percent;
58964
59049
  if (_profit_percent && (position2?.quantity || 0) > 0) {
58965
59050
  _profit = to_f2(position2.quantity * _profit_percent * position2.entry / 100);
59051
+ next_risk = risk + _profit;
58966
59052
  }
58967
59053
  await this.app_db.update_db_position(position2, {
58968
- target_pnl: _profit
59054
+ target_pnl: _profit,
59055
+ next_risk
58969
59056
  });
58970
59057
  return _profit;
58971
59058
  }
58972
59059
  return 0;
58973
59060
  }
59061
+ async updateRiskOnEmpty(payload) {
59062
+ const { symbol, kind } = payload;
59063
+ const position2 = await this.syncAccount({
59064
+ symbol,
59065
+ kind
59066
+ });
59067
+ if (position2 && position2.quantity === 0) {
59068
+ if (position2.next_risk && position2.next_risk > 0) {
59069
+ await this.getPositionConfig({
59070
+ symbol,
59071
+ kind,
59072
+ params: {
59073
+ risk: position2.next_risk
59074
+ }
59075
+ });
59076
+ console.log(`Updated ${kind} position config for ${symbol}: risk = ${position2.next_risk}`);
59077
+ return {
59078
+ updated: true,
59079
+ symbol,
59080
+ kind,
59081
+ old_risk: position2.expand?.config?.risk,
59082
+ new_risk: position2.next_risk
59083
+ };
59084
+ }
59085
+ }
59086
+ return {
59087
+ updated: false,
59088
+ symbol,
59089
+ kind,
59090
+ reason: position2 ? position2.quantity > 0 ? "Position not empty" : "No next_risk available" : "Position not found"
59091
+ };
59092
+ }
58974
59093
  async updateGoodHedgeConfig(payload) {
58975
59094
  const {
58976
59095
  params,
@@ -60026,6 +60145,38 @@ class ExchangeAccount {
60026
60145
  decimal_places: symbol_config.decimal_places
60027
60146
  });
60028
60147
  }
60148
+ async placeCompoundShortTrade(payload) {
60149
+ }
60150
+ async placeCompoundLongTrade(payload) {
60151
+ const { symbol, params, place = false } = payload;
60152
+ if (place) {
60153
+ await this.getPositionConfig({
60154
+ symbol,
60155
+ kind: "long",
60156
+ params: {
60157
+ entry: params.resistance,
60158
+ stop: params.support,
60159
+ risk_reward: params.risk_reward,
60160
+ risk: params.risk,
60161
+ profit_percent: params.profit_percent
60162
+ }
60163
+ });
60164
+ const short_position = await this.syncAccount({
60165
+ symbol,
60166
+ kind: "short",
60167
+ as_view: true
60168
+ });
60169
+ if (short_position.quantity >= short_position.avg_qty) {
60170
+ await this.placeTrade({
60171
+ symbol,
60172
+ kind: "long",
60173
+ ignore_config: true,
60174
+ limit: true,
60175
+ place: true
60176
+ });
60177
+ }
60178
+ }
60179
+ }
60029
60180
  }
60030
60181
  function getExchangeKlass(exchange) {
60031
60182
  const func = exchange === "binance" ? BinanceExchange : BybitExchange;
@@ -60366,6 +60517,43 @@ class App {
60366
60517
  });
60367
60518
  return result;
60368
60519
  }
60520
+ async compoundLongTrade(payload) {
60521
+ const { main_account, focus_account, rr, place } = payload;
60522
+ const main_exchange_account = await this.getExchangeAccount(main_account);
60523
+ const focus_exchange_account = await this.getExchangeAccount(focus_account);
60524
+ const focus_position = await focus_exchange_account.syncAccount({
60525
+ symbol: focus_account.symbol,
60526
+ as_view: true
60527
+ });
60528
+ const focus_long_position = focus_position.find((k) => k.kind === "long");
60529
+ const focus_short_position = focus_position.find((k) => k.kind === "short");
60530
+ const shortConfig = await main_exchange_account.getPositionConfig({
60531
+ symbol: main_account.symbol,
60532
+ kind: "short"
60533
+ });
60534
+ const symbol_config = await focus_exchange_account.recomputeSymbolConfig({
60535
+ symbol: focus_account.symbol
60536
+ });
60537
+ const result = determineCompoundLongTrade({
60538
+ focus_short_position,
60539
+ focus_long_position,
60540
+ shortConfig,
60541
+ global_config: symbol_config,
60542
+ rr
60543
+ });
60544
+ await main_exchange_account.placeCompoundLongTrade({
60545
+ symbol: main_account.symbol,
60546
+ params: {
60547
+ resistance: result.resistance,
60548
+ support: result.support,
60549
+ profit_percent: result.profit_percent,
60550
+ risk_reward: result.result.risk_reward,
60551
+ risk: result.result.risk
60552
+ },
60553
+ place
60554
+ });
60555
+ return result;
60556
+ }
60369
60557
  async reduceExistingPosition(payload) {
60370
60558
  const {
60371
60559
  main_account,
@@ -60507,6 +60695,7 @@ export {
60507
60695
  determineRewardFactor,
60508
60696
  determineOptimumRisk,
60509
60697
  determineOptimumReward,
60698
+ determineCompoundLongTrade,
60510
60699
  exports_database as database,
60511
60700
  createArray,
60512
60701
  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,54 @@ 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 diff = short_profit * rr / short_app_config.last_value.avg_size;
61167
+ const support = Math.abs(short_app_config.last_value.avg_entry - diff);
61168
+ const resistance = focus_short_position.next_order || focus_long_position.take_profit;
61169
+ console.log({ support, resistance, short_profit });
61170
+ const result = getRiskReward({
61171
+ entry: resistance,
61172
+ stop: support,
61173
+ risk: start_risk,
61174
+ global_config,
61175
+ force_exact_risk: true
61176
+ });
61177
+ const long_app_config = buildAppConfig(global_config, {
61178
+ entry: resistance,
61179
+ stop: support,
61180
+ risk_reward: result.risk_reward,
61181
+ risk: result.risk,
61182
+ symbol: shortConfig.symbol
61183
+ });
61184
+ const long_profit_percent = start_risk * 2 * 100 / (long_app_config.last_value.avg_size * long_app_config.last_value.avg_entry);
61185
+ return {
61186
+ start_risk,
61187
+ short_profit,
61188
+ support: to_f2(support, global_config.price_places),
61189
+ resistance: to_f2(resistance, global_config.price_places),
61190
+ long_v: long_app_config.last_value,
61191
+ profit_percent: to_f2(long_profit_percent, "%.3f"),
61192
+ result,
61193
+ short_max_size
61194
+ };
61195
+ }
61117
61196
 
61118
61197
  // src/helpers/strategy.ts
61119
61198
  class Strategy {
@@ -65197,6 +65276,10 @@ class ExchangeAccount {
65197
65276
  symbol,
65198
65277
  kind
65199
65278
  });
65279
+ await this.updateRiskOnEmpty({
65280
+ symbol,
65281
+ kind
65282
+ });
65200
65283
  }
65201
65284
  const long_config = await this.getPositionConfig({
65202
65285
  symbol,
@@ -65688,17 +65771,53 @@ class ExchangeAccount {
65688
65771
  if (position2?.expand?.config) {
65689
65772
  const config2 = position2.expand.config;
65690
65773
  let _profit = config2.profit;
65774
+ let risk = config2.risk;
65775
+ let next_risk = position2.next_risk;
65691
65776
  let _profit_percent = config2?.profit_percent;
65692
65777
  if (_profit_percent && (position2?.quantity || 0) > 0) {
65693
65778
  _profit = to_f2(position2.quantity * _profit_percent * position2.entry / 100);
65779
+ next_risk = risk + _profit;
65694
65780
  }
65695
65781
  await this.app_db.update_db_position(position2, {
65696
- target_pnl: _profit
65782
+ target_pnl: _profit,
65783
+ next_risk
65697
65784
  });
65698
65785
  return _profit;
65699
65786
  }
65700
65787
  return 0;
65701
65788
  }
65789
+ async updateRiskOnEmpty(payload) {
65790
+ const { symbol, kind } = payload;
65791
+ const position2 = await this.syncAccount({
65792
+ symbol,
65793
+ kind
65794
+ });
65795
+ if (position2 && position2.quantity === 0) {
65796
+ if (position2.next_risk && position2.next_risk > 0) {
65797
+ await this.getPositionConfig({
65798
+ symbol,
65799
+ kind,
65800
+ params: {
65801
+ risk: position2.next_risk
65802
+ }
65803
+ });
65804
+ console.log(`Updated ${kind} position config for ${symbol}: risk = ${position2.next_risk}`);
65805
+ return {
65806
+ updated: true,
65807
+ symbol,
65808
+ kind,
65809
+ old_risk: position2.expand?.config?.risk,
65810
+ new_risk: position2.next_risk
65811
+ };
65812
+ }
65813
+ }
65814
+ return {
65815
+ updated: false,
65816
+ symbol,
65817
+ kind,
65818
+ reason: position2 ? position2.quantity > 0 ? "Position not empty" : "No next_risk available" : "Position not found"
65819
+ };
65820
+ }
65702
65821
  async updateGoodHedgeConfig(payload) {
65703
65822
  const {
65704
65823
  params,
@@ -66754,6 +66873,38 @@ class ExchangeAccount {
66754
66873
  decimal_places: symbol_config.decimal_places
66755
66874
  });
66756
66875
  }
66876
+ async placeCompoundShortTrade(payload) {
66877
+ }
66878
+ async placeCompoundLongTrade(payload) {
66879
+ const { symbol, params, place = false } = payload;
66880
+ if (place) {
66881
+ await this.getPositionConfig({
66882
+ symbol,
66883
+ kind: "long",
66884
+ params: {
66885
+ entry: params.resistance,
66886
+ stop: params.support,
66887
+ risk_reward: params.risk_reward,
66888
+ risk: params.risk,
66889
+ profit_percent: params.profit_percent
66890
+ }
66891
+ });
66892
+ const short_position = await this.syncAccount({
66893
+ symbol,
66894
+ kind: "short",
66895
+ as_view: true
66896
+ });
66897
+ if (short_position.quantity >= short_position.avg_qty) {
66898
+ await this.placeTrade({
66899
+ symbol,
66900
+ kind: "long",
66901
+ ignore_config: true,
66902
+ limit: true,
66903
+ place: true
66904
+ });
66905
+ }
66906
+ }
66907
+ }
66757
66908
  }
66758
66909
  function getExchangeKlass(exchange) {
66759
66910
  const func = exchange === "binance" ? BinanceExchange : BybitExchange;
@@ -67094,6 +67245,43 @@ class App {
67094
67245
  });
67095
67246
  return result;
67096
67247
  }
67248
+ async compoundLongTrade(payload) {
67249
+ const { main_account, focus_account, rr, place } = payload;
67250
+ const main_exchange_account = await this.getExchangeAccount(main_account);
67251
+ const focus_exchange_account = await this.getExchangeAccount(focus_account);
67252
+ const focus_position = await focus_exchange_account.syncAccount({
67253
+ symbol: focus_account.symbol,
67254
+ as_view: true
67255
+ });
67256
+ const focus_long_position = focus_position.find((k) => k.kind === "long");
67257
+ const focus_short_position = focus_position.find((k) => k.kind === "short");
67258
+ const shortConfig = await main_exchange_account.getPositionConfig({
67259
+ symbol: main_account.symbol,
67260
+ kind: "short"
67261
+ });
67262
+ const symbol_config = await focus_exchange_account.recomputeSymbolConfig({
67263
+ symbol: focus_account.symbol
67264
+ });
67265
+ const result = determineCompoundLongTrade({
67266
+ focus_short_position,
67267
+ focus_long_position,
67268
+ shortConfig,
67269
+ global_config: symbol_config,
67270
+ rr
67271
+ });
67272
+ await main_exchange_account.placeCompoundLongTrade({
67273
+ symbol: main_account.symbol,
67274
+ params: {
67275
+ resistance: result.resistance,
67276
+ support: result.support,
67277
+ profit_percent: result.profit_percent,
67278
+ risk_reward: result.result.risk_reward,
67279
+ risk: result.result.risk
67280
+ },
67281
+ place
67282
+ });
67283
+ return result;
67284
+ }
67097
67285
  async reduceExistingPosition(payload) {
67098
67286
  const {
67099
67287
  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,54 @@ 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 diff = short_profit * rr / short_app_config.last_value.avg_size;
61144
+ const support = Math.abs(short_app_config.last_value.avg_entry - diff);
61145
+ const resistance = focus_short_position.next_order || focus_long_position.take_profit;
61146
+ console.log({ support, resistance, short_profit });
61147
+ const result = getRiskReward({
61148
+ entry: resistance,
61149
+ stop: support,
61150
+ risk: start_risk,
61151
+ global_config,
61152
+ force_exact_risk: true
61153
+ });
61154
+ const long_app_config = buildAppConfig(global_config, {
61155
+ entry: resistance,
61156
+ stop: support,
61157
+ risk_reward: result.risk_reward,
61158
+ risk: result.risk,
61159
+ symbol: shortConfig.symbol
61160
+ });
61161
+ const long_profit_percent = start_risk * 2 * 100 / (long_app_config.last_value.avg_size * long_app_config.last_value.avg_entry);
61162
+ return {
61163
+ start_risk,
61164
+ short_profit,
61165
+ support: to_f2(support, global_config.price_places),
61166
+ resistance: to_f2(resistance, global_config.price_places),
61167
+ long_v: long_app_config.last_value,
61168
+ profit_percent: to_f2(long_profit_percent, "%.3f"),
61169
+ result,
61170
+ short_max_size
61171
+ };
61172
+ }
61094
61173
 
61095
61174
  // src/helpers/strategy.ts
61096
61175
  class Strategy {
@@ -65174,6 +65253,10 @@ class ExchangeAccount {
65174
65253
  symbol,
65175
65254
  kind
65176
65255
  });
65256
+ await this.updateRiskOnEmpty({
65257
+ symbol,
65258
+ kind
65259
+ });
65177
65260
  }
65178
65261
  const long_config = await this.getPositionConfig({
65179
65262
  symbol,
@@ -65665,17 +65748,53 @@ class ExchangeAccount {
65665
65748
  if (position2?.expand?.config) {
65666
65749
  const config2 = position2.expand.config;
65667
65750
  let _profit = config2.profit;
65751
+ let risk = config2.risk;
65752
+ let next_risk = position2.next_risk;
65668
65753
  let _profit_percent = config2?.profit_percent;
65669
65754
  if (_profit_percent && (position2?.quantity || 0) > 0) {
65670
65755
  _profit = to_f2(position2.quantity * _profit_percent * position2.entry / 100);
65756
+ next_risk = risk + _profit;
65671
65757
  }
65672
65758
  await this.app_db.update_db_position(position2, {
65673
- target_pnl: _profit
65759
+ target_pnl: _profit,
65760
+ next_risk
65674
65761
  });
65675
65762
  return _profit;
65676
65763
  }
65677
65764
  return 0;
65678
65765
  }
65766
+ async updateRiskOnEmpty(payload) {
65767
+ const { symbol, kind } = payload;
65768
+ const position2 = await this.syncAccount({
65769
+ symbol,
65770
+ kind
65771
+ });
65772
+ if (position2 && position2.quantity === 0) {
65773
+ if (position2.next_risk && position2.next_risk > 0) {
65774
+ await this.getPositionConfig({
65775
+ symbol,
65776
+ kind,
65777
+ params: {
65778
+ risk: position2.next_risk
65779
+ }
65780
+ });
65781
+ console.log(`Updated ${kind} position config for ${symbol}: risk = ${position2.next_risk}`);
65782
+ return {
65783
+ updated: true,
65784
+ symbol,
65785
+ kind,
65786
+ old_risk: position2.expand?.config?.risk,
65787
+ new_risk: position2.next_risk
65788
+ };
65789
+ }
65790
+ }
65791
+ return {
65792
+ updated: false,
65793
+ symbol,
65794
+ kind,
65795
+ reason: position2 ? position2.quantity > 0 ? "Position not empty" : "No next_risk available" : "Position not found"
65796
+ };
65797
+ }
65679
65798
  async updateGoodHedgeConfig(payload) {
65680
65799
  const {
65681
65800
  params,
@@ -66731,6 +66850,38 @@ class ExchangeAccount {
66731
66850
  decimal_places: symbol_config.decimal_places
66732
66851
  });
66733
66852
  }
66853
+ async placeCompoundShortTrade(payload) {
66854
+ }
66855
+ async placeCompoundLongTrade(payload) {
66856
+ const { symbol, params, place = false } = payload;
66857
+ if (place) {
66858
+ await this.getPositionConfig({
66859
+ symbol,
66860
+ kind: "long",
66861
+ params: {
66862
+ entry: params.resistance,
66863
+ stop: params.support,
66864
+ risk_reward: params.risk_reward,
66865
+ risk: params.risk,
66866
+ profit_percent: params.profit_percent
66867
+ }
66868
+ });
66869
+ const short_position = await this.syncAccount({
66870
+ symbol,
66871
+ kind: "short",
66872
+ as_view: true
66873
+ });
66874
+ if (short_position.quantity >= short_position.avg_qty) {
66875
+ await this.placeTrade({
66876
+ symbol,
66877
+ kind: "long",
66878
+ ignore_config: true,
66879
+ limit: true,
66880
+ place: true
66881
+ });
66882
+ }
66883
+ }
66884
+ }
66734
66885
  }
66735
66886
  function getExchangeKlass(exchange) {
66736
66887
  const func = exchange === "binance" ? BinanceExchange : BybitExchange;
@@ -67071,6 +67222,43 @@ class App {
67071
67222
  });
67072
67223
  return result;
67073
67224
  }
67225
+ async compoundLongTrade(payload) {
67226
+ const { main_account, focus_account, rr, place } = payload;
67227
+ const main_exchange_account = await this.getExchangeAccount(main_account);
67228
+ const focus_exchange_account = await this.getExchangeAccount(focus_account);
67229
+ const focus_position = await focus_exchange_account.syncAccount({
67230
+ symbol: focus_account.symbol,
67231
+ as_view: true
67232
+ });
67233
+ const focus_long_position = focus_position.find((k) => k.kind === "long");
67234
+ const focus_short_position = focus_position.find((k) => k.kind === "short");
67235
+ const shortConfig = await main_exchange_account.getPositionConfig({
67236
+ symbol: main_account.symbol,
67237
+ kind: "short"
67238
+ });
67239
+ const symbol_config = await focus_exchange_account.recomputeSymbolConfig({
67240
+ symbol: focus_account.symbol
67241
+ });
67242
+ const result = determineCompoundLongTrade({
67243
+ focus_short_position,
67244
+ focus_long_position,
67245
+ shortConfig,
67246
+ global_config: symbol_config,
67247
+ rr
67248
+ });
67249
+ await main_exchange_account.placeCompoundLongTrade({
67250
+ symbol: main_account.symbol,
67251
+ params: {
67252
+ resistance: result.resistance,
67253
+ support: result.support,
67254
+ profit_percent: result.profit_percent,
67255
+ risk_reward: result.result.risk_reward,
67256
+ risk: result.result.risk
67257
+ },
67258
+ place
67259
+ });
67260
+ return result;
67261
+ }
67074
67262
  async reduceExistingPosition(payload) {
67075
67263
  const {
67076
67264
  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-132",
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
  },