@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.
- package/dist/frontend-index.d.ts +308 -13
- package/dist/frontend-index.js +419 -6
- package/dist/index.cjs +457 -44
- package/dist/index.d.ts +309 -11
- package/dist/index.js +457 -44
- package/dist/mcp-server.cjs +737 -4
- package/dist/mcp-server.js +737 -4
- package/package.json +1 -1
package/dist/frontend-index.js
CHANGED
|
@@ -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
|
-
|
|
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,
|