@gbozee/ultimate 0.0.2-200 → 0.0.2-202

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.
@@ -653,7 +653,6 @@ class Signal {
653
653
  let potentials = new_result.filter((x) => condition(x["entry"], i["risk_sell"])).map((x) => x["entry"]);
654
654
  if (potentials.length && max_index) {
655
655
  if (kind === "long") {
656
- console.log("slice: ", potentials.slice(0, max_index));
657
656
  i["risk_sell"] = Math.max(...potentials.slice(0, max_index));
658
657
  } else {
659
658
  i["risk_sell"] = Math.min(...potentials.slice(0, max_index));
@@ -717,7 +716,6 @@ class Signal {
717
716
  }) {
718
717
  const margin_zones = [this.support, this.resistance];
719
718
  const distribution = this.distribution ? this.distribution[kind] : "geometric";
720
- console.log("margin_zones", { margin_zones, distribution });
721
719
  let _kind = distribution === "inverse-exponential" ? kind === "long" ? "short" : "long" : kind;
722
720
  const entries = distributions_default({
723
721
  margin_range: margin_zones,
@@ -936,7 +934,6 @@ class Signal {
936
934
  }
937
935
  });
938
936
  risk_to_use = theoretical_kelly * risk_per_trade / this.kelly_minimum_risk;
939
- console.log({ risk_per_trade, theoretical_kelly });
940
937
  }
941
938
  const y = this.build_trade_dict({
942
939
  entry: x,
@@ -1647,7 +1644,6 @@ function buildConfig(app_config, {
1647
1644
  }
1648
1645
  const condition = (kind === "long" ? entry > app_config.support : entry >= app_config.support) && stop >= app_config.support * 0.999;
1649
1646
  if (kind === "short") {}
1650
- console.log({ entry, stop, condition, working_risk, config });
1651
1647
  const result = entry === stop ? [] : condition ? instance.build_entry({
1652
1648
  current_price: entry,
1653
1649
  stop_loss: stop,
@@ -2303,6 +2299,7 @@ function computeRiskReward(payload) {
2303
2299
  risk_per_trade,
2304
2300
  target_loss,
2305
2301
  distribution,
2302
+ high_range,
2306
2303
  max_size
2307
2304
  } = payload;
2308
2305
  const kind = entry > stop ? "long" : "short";
@@ -2314,12 +2311,14 @@ function computeRiskReward(payload) {
2314
2311
  app_config,
2315
2312
  target_loss,
2316
2313
  distribution,
2314
+ high_range,
2317
2315
  max_size
2318
2316
  });
2319
2317
  return result;
2320
2318
  }
2321
2319
  function getRiskReward(payload) {
2322
2320
  const {
2321
+ high_range,
2323
2322
  max_size,
2324
2323
  entry,
2325
2324
  stop,
@@ -2343,6 +2342,7 @@ function getRiskReward(payload) {
2343
2342
  entry,
2344
2343
  stop,
2345
2344
  risk_per_trade: risk,
2345
+ high_range,
2346
2346
  target_loss,
2347
2347
  distribution,
2348
2348
  max_size
@@ -3337,13 +3337,425 @@ class Strategy {
3337
3337
  }
3338
3338
  }
3339
3339
  // src/helpers/compound.ts
3340
- var name = "";
3340
+ function buildTrades(payload) {
3341
+ const { appConfig, settings, kind } = payload;
3342
+ const kelly_config = settings.kelly;
3343
+ const current_app_config = { ...appConfig[kind] };
3344
+ const entryNum = parseFloat(settings.entry);
3345
+ const stopNum = parseFloat(settings.stop);
3346
+ current_app_config.entry = entryNum;
3347
+ current_app_config.stop = stopNum;
3348
+ current_app_config.risk_per_trade = parseFloat(settings.risk);
3349
+ current_app_config.risk_reward = parseFloat(settings.risk_reward);
3350
+ current_app_config.kind = kind;
3351
+ current_app_config.kelly = kelly_config;
3352
+ const options = {
3353
+ take_profit: null,
3354
+ entry: current_app_config.entry,
3355
+ stop: current_app_config.stop,
3356
+ raw_instance: null,
3357
+ risk: current_app_config.risk_per_trade,
3358
+ no_of_trades: undefined,
3359
+ risk_reward: current_app_config.risk_reward,
3360
+ kind: current_app_config.kind,
3361
+ increase: true,
3362
+ gap: current_app_config.gap,
3363
+ rr: current_app_config.rr,
3364
+ price_places: current_app_config.price_places,
3365
+ decimal_places: current_app_config.decimal_places,
3366
+ use_kelly: kelly_config?.use_kelly,
3367
+ kelly_confidence_factor: kelly_config?.kelly_confidence_factor,
3368
+ kelly_minimum_risk: kelly_config?.kelly_minimum_risk,
3369
+ kelly_prediction_model: kelly_config?.kelly_prediction_model,
3370
+ kelly_func: kelly_config?.kelly_func,
3371
+ distribution: settings.distribution
3372
+ };
3373
+ if (kind === "long" && entryNum <= stopNum) {
3374
+ return [];
3375
+ }
3376
+ if (kind === "short" && entryNum >= stopNum) {
3377
+ return [];
3378
+ }
3379
+ try {
3380
+ const generatedTrades = sortedBuildConfig(current_app_config, options);
3381
+ return generatedTrades ?? [];
3382
+ } catch (error) {
3383
+ console.error("Error generating orders:", error);
3384
+ return [];
3385
+ }
3386
+ }
3387
+ function generateSummary({
3388
+ trades,
3389
+ fee_percent = 0.05,
3390
+ anchor
3391
+ }) {
3392
+ const avg_entry = trades[0].avg_entry;
3393
+ const avg_size = trades[0].avg_size;
3394
+ const expected_fee = avg_entry * avg_size * fee_percent / 100;
3395
+ return {
3396
+ first_entry: trades.at(-1).entry,
3397
+ last_entry: trades[0].entry,
3398
+ quantity: avg_size,
3399
+ entry: avg_entry,
3400
+ loss: trades[0].neg_pnl,
3401
+ number_of_trades: trades.length,
3402
+ fee: to_f(expected_fee, "%.2f"),
3403
+ anchor_pnl: anchor?.target_pnl
3404
+ };
3405
+ }
3406
+ function helperFuncToBuildTrades({
3407
+ custom_b_config,
3408
+ symbol_config,
3409
+ app_config_kind,
3410
+ appConfig,
3411
+ force_exact_risk = true
3412
+ }) {
3413
+ const risk = custom_b_config.risk * (custom_b_config.risk_factor || 1);
3414
+ let result = getRiskReward({
3415
+ entry: custom_b_config.entry,
3416
+ stop: custom_b_config.stop,
3417
+ risk,
3418
+ global_config: symbol_config,
3419
+ force_exact_risk,
3420
+ target_loss: custom_b_config.risk * (custom_b_config.risk_factor || 1),
3421
+ distribution: custom_b_config.distribution
3422
+ });
3423
+ if (!force_exact_risk) {
3424
+ result = {
3425
+ risk_reward: result,
3426
+ risk
3427
+ };
3428
+ }
3429
+ const trades = result.risk_reward ? buildTrades({
3430
+ appConfig: { [app_config_kind]: appConfig },
3431
+ kind: app_config_kind,
3432
+ settings: {
3433
+ entry: custom_b_config.entry,
3434
+ stop: custom_b_config.stop,
3435
+ risk: result.risk || custom_b_config.risk,
3436
+ risk_reward: result.risk_reward,
3437
+ distribution: custom_b_config.distribution
3438
+ }
3439
+ }) : [];
3440
+ const summary = trades.length > 0 ? generateSummary({ trades }) : {};
3441
+ return { trades, result, summary };
3442
+ }
3443
+ function constructAppConfig2({
3444
+ config,
3445
+ global_config
3446
+ }) {
3447
+ const options = {
3448
+ entry: config?.entry,
3449
+ stop: config?.stop,
3450
+ risk_reward: config?.risk_reward,
3451
+ risk: config?.risk,
3452
+ symbol: config.symbol
3453
+ };
3454
+ const { entries: _entries, ...appConfig } = buildAppConfig(global_config, options);
3455
+ return appConfig;
3456
+ }
3457
+ function buildWithOptimumReward({
3458
+ config,
3459
+ settings,
3460
+ global_config,
3461
+ force_exact
3462
+ }) {
3463
+ const kind = config.entry > config.stop ? "long" : "short";
3464
+ let stop = settings.stop;
3465
+ let entry = settings.entry;
3466
+ const risk = settings.risk;
3467
+ const stop_ratio = settings.stop_ratio || 1;
3468
+ const distribution = settings.distribution || config?.distribution;
3469
+ const custom_b_config = {
3470
+ entry,
3471
+ stop,
3472
+ risk,
3473
+ distribution
3474
+ };
3475
+ const appConfig = constructAppConfig2({
3476
+ config,
3477
+ global_config
3478
+ });
3479
+ const { trades, summary, result } = helperFuncToBuildTrades({
3480
+ custom_b_config,
3481
+ app_config_kind: kind,
3482
+ appConfig,
3483
+ symbol_config: global_config,
3484
+ force_exact_risk: force_exact
3485
+ });
3486
+ const adjusted_size = summary.quantity;
3487
+ const symbol_config = global_config;
3488
+ const entryDetails = {
3489
+ entry: to_f(custom_b_config.entry, symbol_config.price_places),
3490
+ stop: to_f(custom_b_config.stop, symbol_config.price_places),
3491
+ risk: to_f(result.risk, "%.2f"),
3492
+ risk_reward: result.risk_reward,
3493
+ avg_entry: to_f(summary.entry, symbol_config.price_places),
3494
+ avg_size: to_f(adjusted_size, symbol_config.decimal_places),
3495
+ first_entry: to_f(summary.first_entry, symbol_config.price_places),
3496
+ pnl: to_f(custom_b_config.risk, "%.2f"),
3497
+ fee: to_f(summary.fee, "%.2f"),
3498
+ loss: to_f(summary.loss, "%.2f"),
3499
+ last_entry: to_f(summary.last_entry, symbol_config.price_places),
3500
+ margin: to_f(summary.entry * adjusted_size / symbol_config.leverage, "%.2f")
3501
+ };
3502
+ return {
3503
+ trades,
3504
+ summary: entryDetails,
3505
+ config: {
3506
+ ...custom_b_config,
3507
+ ...result,
3508
+ stop_ratio
3509
+ },
3510
+ stop_order: {
3511
+ quantity: entryDetails.avg_size * stop_ratio,
3512
+ price: entryDetails.stop
3513
+ },
3514
+ kind
3515
+ };
3516
+ }
3517
+ function generateOppositeOptimum({
3518
+ config,
3519
+ global_config,
3520
+ settings,
3521
+ ratio = 1,
3522
+ distribution,
3523
+ risk_factor = 1
3524
+ }) {
3525
+ const configKind = config.entry > config.stop ? "long" : "short";
3526
+ if (configKind === "long" && config.entry > config.stop) {
3527
+ if (settings.stop <= settings.entry) {
3528
+ throw new Error("Invalid input: For long config positions, opposite settings must have stop > entry");
3529
+ }
3530
+ } else if (configKind === "short" && config.entry < config.stop) {
3531
+ if (settings.stop >= settings.entry) {
3532
+ throw new Error("Invalid input: For short config positions, opposite settings must have stop < entry");
3533
+ }
3534
+ }
3535
+ const kind = config.entry > config.stop ? "long" : "short";
3536
+ const app_config_kind = kind === "long" ? "short" : "long";
3537
+ let risk = settings.risk;
3538
+ const custom_b_config = {
3539
+ entry: settings.entry,
3540
+ stop: settings.stop,
3541
+ risk: risk * ratio,
3542
+ distribution: distribution || "inverse-exponential",
3543
+ risk_factor
3544
+ };
3545
+ const appConfig = constructAppConfig2({
3546
+ config: {
3547
+ ...config,
3548
+ ...custom_b_config
3549
+ },
3550
+ global_config
3551
+ });
3552
+ const { result, trades, summary } = helperFuncToBuildTrades({
3553
+ custom_b_config,
3554
+ symbol_config: global_config,
3555
+ app_config_kind,
3556
+ appConfig
3557
+ });
3558
+ if (Object.keys(summary).length === 0) {
3559
+ return {
3560
+ trades,
3561
+ summary,
3562
+ config: custom_b_config,
3563
+ kind: app_config_kind
3564
+ };
3565
+ }
3566
+ const symbol_config = global_config;
3567
+ const entryDetails = {
3568
+ entry: to_f(custom_b_config.entry, symbol_config.price_places),
3569
+ stop: to_f(custom_b_config.stop, symbol_config.price_places),
3570
+ risk: to_f(result.risk, "%.2f"),
3571
+ risk_reward: result.risk_reward,
3572
+ avg_entry: to_f(summary.entry, symbol_config.price_places),
3573
+ avg_size: to_f(summary.quantity, symbol_config.decimal_places),
3574
+ first_entry: to_f(summary.first_entry, symbol_config.price_places),
3575
+ pnl: to_f(custom_b_config.risk, "%.2f"),
3576
+ fee: to_f(summary.fee, "%.2f"),
3577
+ loss: to_f(summary.loss, "%.2f"),
3578
+ last_entry: to_f(summary.last_entry, symbol_config.price_places),
3579
+ defaultEntry: settings.entry ? to_f(settings.entry, symbol_config.price_places) : null
3580
+ };
3581
+ return {
3582
+ trades,
3583
+ summary: entryDetails,
3584
+ config: {
3585
+ ...custom_b_config,
3586
+ ...result
3587
+ },
3588
+ kind: app_config_kind
3589
+ };
3590
+ }
3591
+ function defaultTradeFromCurrentState({
3592
+ config,
3593
+ global_config
3594
+ }) {
3595
+ const kind = config.entry > config.stop ? "long" : "short";
3596
+ const settings = {
3597
+ entry: config?.entry,
3598
+ stop: config?.stop,
3599
+ risk: config?.risk,
3600
+ distribution: config?.distribution,
3601
+ risk_reward: config?.risk_reward
3602
+ };
3603
+ const appConfig = constructAppConfig2({
3604
+ config,
3605
+ global_config
3606
+ });
3607
+ const trades = buildTrades({
3608
+ appConfig: { [kind]: appConfig },
3609
+ kind,
3610
+ settings
3611
+ });
3612
+ return {
3613
+ trades,
3614
+ summary: generateSummary({
3615
+ trades,
3616
+ fee_percent: global_config.fee_percent
3617
+ })
3618
+ };
3619
+ }
3620
+ function increaseTradeHelper({
3621
+ increase_qty,
3622
+ stop,
3623
+ config,
3624
+ global_config,
3625
+ style,
3626
+ entry,
3627
+ position: position2,
3628
+ stop_ratio = 1,
3629
+ distribution: default_distribution
3630
+ }) {
3631
+ const symbol_config = global_config;
3632
+ const kind = config.entry > config.stop ? "long" : "short";
3633
+ const distribution = default_distribution || config.distribution || "inverse-exponential";
3634
+ const appConfig = constructAppConfig2({
3635
+ config,
3636
+ global_config
3637
+ });
3638
+ const currentState = defaultTradeFromCurrentState({
3639
+ config,
3640
+ global_config
3641
+ });
3642
+ const { optimal_risk, neg_pnl } = getOptimumStopAndRisk(appConfig, {
3643
+ max_size: increase_qty,
3644
+ target_stop: stop,
3645
+ distribution
3646
+ });
3647
+ if (neg_pnl === 0) {
3648
+ return {
3649
+ trades: [],
3650
+ summary: {},
3651
+ config: {},
3652
+ kind,
3653
+ current: currentState
3654
+ };
3655
+ }
3656
+ const custom_b_config = {
3657
+ entry,
3658
+ stop,
3659
+ risk: style === "minimum" ? Math.abs(neg_pnl) : optimal_risk,
3660
+ distribution
3661
+ };
3662
+ const { result, trades, summary } = helperFuncToBuildTrades({
3663
+ custom_b_config,
3664
+ symbol_config,
3665
+ appConfig,
3666
+ app_config_kind: kind
3667
+ });
3668
+ if (Object.keys(summary).length === 0) {
3669
+ return {
3670
+ trades,
3671
+ summary,
3672
+ config: {
3673
+ ...custom_b_config,
3674
+ ...result
3675
+ },
3676
+ kind,
3677
+ current: currentState
3678
+ };
3679
+ }
3680
+ const new_avg_values = determine_average_entry_and_size([
3681
+ {
3682
+ price: position2.entry,
3683
+ quantity: position2.quantity
3684
+ },
3685
+ {
3686
+ price: summary?.entry,
3687
+ quantity: summary?.quantity
3688
+ }
3689
+ ], symbol_config.decimal_places, symbol_config.price_places);
3690
+ summary.entry = new_avg_values.entry;
3691
+ summary.quantity = new_avg_values.quantity;
3692
+ const loss = Math.abs(summary.entry - custom_b_config.stop) * summary.quantity;
3693
+ const entryDetails = {
3694
+ entry: to_f(custom_b_config.entry, symbol_config.price_places),
3695
+ stop: to_f(custom_b_config.stop, symbol_config.price_places),
3696
+ risk: to_f(result.risk, symbol_config.price_places),
3697
+ risk_reward: result.risk_reward,
3698
+ avg_entry: to_f(summary.entry, symbol_config.price_places),
3699
+ avg_size: to_f(summary.quantity, symbol_config.decimal_places),
3700
+ first_entry: to_f(summary.first_entry, symbol_config.price_places),
3701
+ pnl: to_f(custom_b_config.risk, "%.2f"),
3702
+ fee: to_f(summary.fee, "%.2f"),
3703
+ loss: to_f(loss, "%.2f"),
3704
+ last_entry: to_f(summary.last_entry, symbol_config.price_places),
3705
+ margin: to_f(summary.entry * summary.quantity / global_config.leverage, "%.2f")
3706
+ };
3707
+ return {
3708
+ trades,
3709
+ summary: entryDetails,
3710
+ stop_order: {
3711
+ quantity: entryDetails.avg_size * stop_ratio,
3712
+ price: entryDetails.stop
3713
+ },
3714
+ config: {
3715
+ ...custom_b_config,
3716
+ ...result
3717
+ },
3718
+ kind,
3719
+ current: currentState
3720
+ };
3721
+ }
3722
+ function generatePositionIncreaseTrade({
3723
+ account,
3724
+ zoneAccount,
3725
+ ratio = 0.1,
3726
+ config,
3727
+ global_config,
3728
+ style = "minimum",
3729
+ distribution = "inverse-exponential"
3730
+ }) {
3731
+ const kind = config.entry > config.stop ? "long" : "short";
3732
+ const target_max_quantity = kind === "long" ? account.short.quantity : account.long.quantity;
3733
+ const increase_qty = target_max_quantity * ratio;
3734
+ const entry = zoneAccount.entry;
3735
+ const stop = zoneAccount.stop;
3736
+ return increaseTradeHelper({
3737
+ config,
3738
+ position: account[kind],
3739
+ global_config,
3740
+ entry,
3741
+ stop,
3742
+ style,
3743
+ increase_qty,
3744
+ distribution
3745
+ });
3746
+ }
3747
+ var compoundAPI = {
3748
+ buildWithOptimumReward,
3749
+ constructAppConfig: constructAppConfig2,
3750
+ generateOppositeOptimum,
3751
+ increaseTradeHelper,
3752
+ generatePositionIncreaseTrade
3753
+ };
3341
3754
  export {
3342
3755
  to_f,
3343
3756
  sortedBuildConfig,
3344
3757
  range,
3345
3758
  profitHelper,
3346
- name,
3347
3759
  logWithLineNumber,
3348
3760
  groupIntoPairsWithSumLessThan,
3349
3761
  groupIntoPairs,
@@ -3383,6 +3795,7 @@ export {
3383
3795
  computeSellZones,
3384
3796
  computeRiskReward,
3385
3797
  computeProfitDetail,
3798
+ compoundAPI,
3386
3799
  calculateFactorFromTakeProfit,
3387
3800
  calculateFactorFromSellQuantity,
3388
3801
  buildConfig,