@gbozee/ultimate 0.0.2-176 → 0.0.2-177
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 +106 -4
- package/dist/frontend-index.js +211 -25
- package/dist/index.cjs +256 -58
- package/dist/index.d.ts +132 -9
- package/dist/index.js +256 -58
- package/dist/mcp-server.cjs +256 -58
- package/dist/mcp-server.js +256 -58
- package/package.json +1 -1
package/dist/frontend-index.d.ts
CHANGED
|
@@ -118,6 +118,21 @@ export declare function determineTPSl(payload: {
|
|
|
118
118
|
reduce_quantity: number;
|
|
119
119
|
expected_loss: number;
|
|
120
120
|
};
|
|
121
|
+
export interface GetEntriesParams {
|
|
122
|
+
kind: "long" | "short";
|
|
123
|
+
distribution: "arithmetic" | "geometric" | "normal" | "exponential" | "inverse-exponential";
|
|
124
|
+
margin_range: [
|
|
125
|
+
number,
|
|
126
|
+
number
|
|
127
|
+
];
|
|
128
|
+
risk_reward: number;
|
|
129
|
+
price_places?: string;
|
|
130
|
+
distribution_params?: {
|
|
131
|
+
curveFactor?: number;
|
|
132
|
+
stdDevFactor?: number;
|
|
133
|
+
lambda?: number;
|
|
134
|
+
};
|
|
135
|
+
}
|
|
121
136
|
export type SignalConfigType = {
|
|
122
137
|
symbol?: string;
|
|
123
138
|
focus: number;
|
|
@@ -145,6 +160,10 @@ export type SignalConfigType = {
|
|
|
145
160
|
kelly_confidence_factor?: number;
|
|
146
161
|
kelly_minimum_risk?: number;
|
|
147
162
|
kelly_func?: "theoretical" | "position_based" | "theoretical_fixed";
|
|
163
|
+
full_distribution?: {
|
|
164
|
+
long: GetEntriesParams["distribution"];
|
|
165
|
+
short: GetEntriesParams["distribution"];
|
|
166
|
+
};
|
|
148
167
|
};
|
|
149
168
|
declare class Signal {
|
|
150
169
|
focus: number;
|
|
@@ -173,8 +192,12 @@ declare class Signal {
|
|
|
173
192
|
kelly_minimum_risk: number;
|
|
174
193
|
kelly_func: "theoretical" | "position_based" | "theoretical_fixed";
|
|
175
194
|
symbol?: string;
|
|
176
|
-
|
|
177
|
-
|
|
195
|
+
distribution: {
|
|
196
|
+
long: GetEntriesParams["distribution"];
|
|
197
|
+
short: GetEntriesParams["distribution"];
|
|
198
|
+
};
|
|
199
|
+
constructor({ focus, symbol, budget, percent_change, price_places, decimal_places, zone_risk, fee, support, risk_reward, resistance, risk_per_trade, increase_size, additional_increase, minimum_pnl, take_profit, increase_position, minimum_size, first_order_size, gap, max_size, use_kelly, kelly_prediction_model, kelly_confidence_factor, kelly_minimum_risk, kelly_func, full_distribution, }: SignalConfigType);
|
|
200
|
+
build_entry({ current_price, stop_loss, pnl, stop_percent, kind, risk, no_of_trades, take_profit, distribution, }: {
|
|
178
201
|
take_profit?: number;
|
|
179
202
|
no_of_trades?: number;
|
|
180
203
|
current_price: number;
|
|
@@ -183,6 +206,7 @@ declare class Signal {
|
|
|
183
206
|
risk: number;
|
|
184
207
|
stop_percent?: number;
|
|
185
208
|
pnl?: number;
|
|
209
|
+
distribution?: GetEntriesParams["distribution"];
|
|
186
210
|
}): any;
|
|
187
211
|
get risk(): number;
|
|
188
212
|
get min_trades(): number;
|
|
@@ -216,6 +240,11 @@ declare class Signal {
|
|
|
216
240
|
kind?: "long" | "short";
|
|
217
241
|
limit?: boolean;
|
|
218
242
|
}): any;
|
|
243
|
+
get_future_zones_simple({ current_price, kind, raw, }: {
|
|
244
|
+
raw?: boolean;
|
|
245
|
+
current_price: number;
|
|
246
|
+
kind?: "long" | "short";
|
|
247
|
+
}): number[];
|
|
219
248
|
get_future_zones({ current_price, kind, raw, }: {
|
|
220
249
|
raw?: boolean;
|
|
221
250
|
current_price: number;
|
|
@@ -329,6 +358,7 @@ export interface ScheduledTrade extends BaseSystemFields {
|
|
|
329
358
|
kelly_minimum_risk?: number;
|
|
330
359
|
kelly_prediction_model?: "exponential" | "normal" | "uniform";
|
|
331
360
|
};
|
|
361
|
+
distribution?: GetEntriesParams["distribution"];
|
|
332
362
|
}
|
|
333
363
|
export interface AccountStrategy extends BaseSystemFields {
|
|
334
364
|
account: string;
|
|
@@ -388,8 +418,36 @@ export interface PositionsView {
|
|
|
388
418
|
b_config?: ScheduledTrade;
|
|
389
419
|
proxy?: Proxy$1;
|
|
390
420
|
account_strategy?: AccountStrategy;
|
|
421
|
+
compound_instance?: CompoundInstance;
|
|
422
|
+
support?: SupportTable;
|
|
391
423
|
};
|
|
392
424
|
pnl?: number;
|
|
425
|
+
support_price?: number;
|
|
426
|
+
}
|
|
427
|
+
export interface Compounder extends BaseSystemFields {
|
|
428
|
+
risk?: number;
|
|
429
|
+
profit_percent?: number;
|
|
430
|
+
owner?: string;
|
|
431
|
+
completed?: boolean;
|
|
432
|
+
start_balance?: number;
|
|
433
|
+
starting_risk?: number;
|
|
434
|
+
fee_rate?: number;
|
|
435
|
+
}
|
|
436
|
+
export interface CompoundInstance extends BaseSystemFields {
|
|
437
|
+
ref?: string;
|
|
438
|
+
position?: string;
|
|
439
|
+
risk?: number;
|
|
440
|
+
hedged?: boolean;
|
|
441
|
+
expand?: {
|
|
442
|
+
ref?: Compounder;
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
export interface SupportTable extends BaseSystemFields {
|
|
446
|
+
symbol?: string;
|
|
447
|
+
price?: number;
|
|
448
|
+
counter?: number;
|
|
449
|
+
last_updated?: string;
|
|
450
|
+
kind?: "long" | "short";
|
|
393
451
|
}
|
|
394
452
|
export type AppConfig = {
|
|
395
453
|
fee: number;
|
|
@@ -442,13 +500,15 @@ export type ExtendConfigType = {
|
|
|
442
500
|
kind?: "long" | "short";
|
|
443
501
|
gap?: number;
|
|
444
502
|
rr?: number;
|
|
503
|
+
min_avg_size?: number;
|
|
445
504
|
use_kelly?: boolean;
|
|
446
505
|
kelly_confidence_factor?: number;
|
|
447
506
|
kelly_minimum_risk?: number;
|
|
448
507
|
kelly_prediction_model?: "exponential" | "normal" | "uniform";
|
|
449
508
|
kelly_func?: "theoretical" | "position_based" | "theoretical_fixed";
|
|
509
|
+
distribution?: GetEntriesParams["distribution"];
|
|
450
510
|
};
|
|
451
|
-
export declare function buildConfig(app_config: AppConfig, { take_profit, entry, stop, raw_instance, risk, no_of_trades, min_profit, risk_reward, kind, increase, gap, rr, price_places, decimal_places, use_kelly, kelly_confidence_factor, kelly_minimum_risk, kelly_prediction_model, kelly_func, }: ExtendConfigType): any[] | Signal;
|
|
511
|
+
export declare function buildConfig(app_config: AppConfig, { take_profit, entry, stop, raw_instance, risk, no_of_trades, min_profit, risk_reward, kind, increase, gap, rr, price_places, decimal_places, use_kelly, kelly_confidence_factor, kelly_minimum_risk, kelly_prediction_model, kelly_func, min_avg_size, distribution, }: ExtendConfigType): any[] | Signal;
|
|
452
512
|
export declare function buildAvg({ _trades, kind, }: {
|
|
453
513
|
_trades: any[];
|
|
454
514
|
kind: "long" | "short";
|
|
@@ -463,6 +523,7 @@ export declare function get_app_config_and_max_size(config: GlobalConfig, payloa
|
|
|
463
523
|
kelly_minimum_risk?: number;
|
|
464
524
|
kelly_prediction_model?: "exponential" | "normal" | "uniform";
|
|
465
525
|
kelly_func?: "theoretical" | "position_based" | "theoretical_fixed";
|
|
526
|
+
distribution?: GetEntriesParams["distribution"];
|
|
466
527
|
}): {
|
|
467
528
|
app_config: AppConfig;
|
|
468
529
|
max_size: any;
|
|
@@ -487,11 +548,13 @@ export declare function buildAppConfig(config: GlobalConfig, payload: {
|
|
|
487
548
|
kelly_minimum_risk?: number;
|
|
488
549
|
kelly_prediction_model?: "exponential" | "normal" | "uniform";
|
|
489
550
|
kelly_func?: "theoretical" | "position_based" | "theoretical_fixed";
|
|
551
|
+
distribution?: GetEntriesParams["distribution"];
|
|
490
552
|
}): AppConfig;
|
|
491
553
|
export declare function getOptimumStopAndRisk(app_config: AppConfig, params: {
|
|
492
554
|
max_size: number;
|
|
493
555
|
target_stop: number;
|
|
494
556
|
highest_risk?: number;
|
|
557
|
+
distribution?: GetEntriesParams["distribution"];
|
|
495
558
|
}): {
|
|
496
559
|
optimal_stop: number;
|
|
497
560
|
optimal_risk: number;
|
|
@@ -548,6 +611,7 @@ export declare function generateOptimumAppConfig(config: GlobalConfig, payload:
|
|
|
548
611
|
risk_reward: number;
|
|
549
612
|
start_risk: number;
|
|
550
613
|
max_risk?: number;
|
|
614
|
+
distribution?: GetEntriesParams["distribution"];
|
|
551
615
|
}, position: {
|
|
552
616
|
entry: number;
|
|
553
617
|
quantity: number;
|
|
@@ -559,6 +623,7 @@ export declare function determineOptimumReward(payload: {
|
|
|
559
623
|
low_range?: number;
|
|
560
624
|
high_range?: number;
|
|
561
625
|
target_loss?: number;
|
|
626
|
+
distribution?: GetEntriesParams["distribution"];
|
|
562
627
|
}): number | {
|
|
563
628
|
result: any[];
|
|
564
629
|
value: number;
|
|
@@ -575,6 +640,7 @@ export declare function determineOptimumRisk(config: GlobalConfig, payload: {
|
|
|
575
640
|
risk_reward: number;
|
|
576
641
|
risk: number;
|
|
577
642
|
symbol: string;
|
|
643
|
+
distribution?: GetEntriesParams["distribution"];
|
|
578
644
|
}, params: {
|
|
579
645
|
highest_risk: number;
|
|
580
646
|
tolerance?: number;
|
|
@@ -596,6 +662,7 @@ export declare function computeRiskReward(payload: {
|
|
|
596
662
|
stop: number;
|
|
597
663
|
risk_per_trade: number;
|
|
598
664
|
target_loss?: number;
|
|
665
|
+
distribution?: GetEntriesParams["distribution"];
|
|
599
666
|
}): number | {
|
|
600
667
|
result: any[];
|
|
601
668
|
value: number;
|
|
@@ -613,6 +680,7 @@ export declare function getRiskReward(payload: {
|
|
|
613
680
|
global_config: GlobalConfig;
|
|
614
681
|
force_exact_risk?: boolean;
|
|
615
682
|
target_loss?: number;
|
|
683
|
+
distribution?: GetEntriesParams["distribution"];
|
|
616
684
|
}): any;
|
|
617
685
|
export declare function computeProfitDetail(payload: {
|
|
618
686
|
focus_position: {
|
|
@@ -840,7 +908,41 @@ export declare function constructAppConfig(payload: {
|
|
|
840
908
|
kelly_minimum_risk: number;
|
|
841
909
|
kelly_prediction_model: string;
|
|
842
910
|
};
|
|
843
|
-
}):
|
|
911
|
+
}): {
|
|
912
|
+
fee: number;
|
|
913
|
+
risk_per_trade: number;
|
|
914
|
+
risk_reward: number;
|
|
915
|
+
symbol?: string;
|
|
916
|
+
focus: number;
|
|
917
|
+
budget: number;
|
|
918
|
+
support: number;
|
|
919
|
+
resistance: number;
|
|
920
|
+
percent_change: number;
|
|
921
|
+
tradeSplit?: number;
|
|
922
|
+
take_profit?: number;
|
|
923
|
+
kind: "long" | "short";
|
|
924
|
+
entry: number;
|
|
925
|
+
stop: number;
|
|
926
|
+
min_size: number;
|
|
927
|
+
price_places?: string;
|
|
928
|
+
strategy?: "quantity" | "entry";
|
|
929
|
+
as_array?: boolean;
|
|
930
|
+
decimal_places?: string;
|
|
931
|
+
min_profit?: number;
|
|
932
|
+
raw?: boolean;
|
|
933
|
+
gap?: number;
|
|
934
|
+
rr?: number;
|
|
935
|
+
max_size?: number;
|
|
936
|
+
last_value?: any;
|
|
937
|
+
max_quantity?: number;
|
|
938
|
+
kelly?: {
|
|
939
|
+
use_kelly?: boolean;
|
|
940
|
+
kelly_confidence_factor?: number;
|
|
941
|
+
kelly_minimum_risk?: number;
|
|
942
|
+
kelly_prediction_model?: "exponential" | "normal" | "uniform";
|
|
943
|
+
kelly_func?: "theoretical" | "position_based" | "theoretical_fixed";
|
|
944
|
+
};
|
|
945
|
+
};
|
|
844
946
|
export declare function generateDangerousConfig(payload: {
|
|
845
947
|
account: PositionsView;
|
|
846
948
|
global_config: GlobalConfig;
|
package/dist/frontend-index.js
CHANGED
|
@@ -1,3 +1,134 @@
|
|
|
1
|
+
// src/helpers/distributions.ts
|
|
2
|
+
function generateArithmetic(payload) {
|
|
3
|
+
const { margin_range, risk_reward, kind, price_places = "%.1f" } = payload;
|
|
4
|
+
const difference = Math.abs(margin_range[1] - margin_range[0]);
|
|
5
|
+
const spread = difference / risk_reward;
|
|
6
|
+
return Array.from({ length: risk_reward + 1 }, (_, i) => {
|
|
7
|
+
const price = kind === "long" ? margin_range[1] - spread * i : margin_range[0] + spread * i;
|
|
8
|
+
return to_f(price, price_places);
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
function generateGeometric(payload) {
|
|
12
|
+
const { margin_range, risk_reward, kind, price_places = "%.1f", percent_change } = payload;
|
|
13
|
+
const effectivePercentChange = percent_change ?? Math.abs(margin_range[1] / margin_range[0] - 1) / risk_reward;
|
|
14
|
+
return Array.from({ length: risk_reward + 1 }, (_, i) => {
|
|
15
|
+
const price = kind === "long" ? margin_range[1] * Math.pow(1 - effectivePercentChange, i) : margin_range[0] * Math.pow(1 + effectivePercentChange, i);
|
|
16
|
+
return to_f(price, price_places);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
function approximateInverseNormal(p) {
|
|
20
|
+
p = Math.max(0.0001, Math.min(0.9999, p));
|
|
21
|
+
if (p < 0.5) {
|
|
22
|
+
const t = Math.sqrt(-2 * Math.log(p));
|
|
23
|
+
const c0 = 2.515517, c1 = 0.802853, c2 = 0.010328;
|
|
24
|
+
const d1 = 1.432788, d2 = 0.189269, d3 = 0.001308;
|
|
25
|
+
return -(t - (c0 + c1 * t + c2 * t * t) / (1 + d1 * t + d2 * t * t + d3 * t * t * t));
|
|
26
|
+
} else {
|
|
27
|
+
const t = Math.sqrt(-2 * Math.log(1 - p));
|
|
28
|
+
const c0 = 2.515517, c1 = 0.802853, c2 = 0.010328;
|
|
29
|
+
const d1 = 1.432788, d2 = 0.189269, d3 = 0.001308;
|
|
30
|
+
return t - (c0 + c1 * t + c2 * t * t) / (1 + d1 * t + d2 * t * t + d3 * t * t * t);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function generateNormal(payload) {
|
|
34
|
+
const { margin_range, risk_reward, kind, price_places = "%.1f", stdDevFactor = 6 } = payload;
|
|
35
|
+
const mean = (margin_range[0] + margin_range[1]) / 2;
|
|
36
|
+
const stdDev = Math.abs(margin_range[1] - margin_range[0]) / stdDevFactor;
|
|
37
|
+
const skew = kind === "long" ? -0.2 : 0.2;
|
|
38
|
+
const adjustedMean = mean + stdDev * skew;
|
|
39
|
+
const entries = Array.from({ length: risk_reward + 1 }, (_, i) => {
|
|
40
|
+
const p = (i + 0.5) / (risk_reward + 1);
|
|
41
|
+
const z = approximateInverseNormal(p);
|
|
42
|
+
let price = adjustedMean + stdDev * z;
|
|
43
|
+
price = Math.max(margin_range[0], Math.min(margin_range[1], price));
|
|
44
|
+
return to_f(price, price_places);
|
|
45
|
+
});
|
|
46
|
+
return entries.sort((a, b) => a - b);
|
|
47
|
+
}
|
|
48
|
+
function generateExponential(payload) {
|
|
49
|
+
const { margin_range, risk_reward, kind, price_places = "%.1f", lambda } = payload;
|
|
50
|
+
const range = Math.abs(margin_range[1] - margin_range[0]);
|
|
51
|
+
const effectiveLambda = lambda || 2.5;
|
|
52
|
+
return Array.from({ length: risk_reward + 1 }, (_, i) => {
|
|
53
|
+
const t = i / risk_reward;
|
|
54
|
+
const exponentialProgress = 1 - Math.exp(-effectiveLambda * t);
|
|
55
|
+
const price = kind === "long" ? margin_range[1] - range * exponentialProgress : margin_range[0] + range * exponentialProgress;
|
|
56
|
+
return to_f(price, price_places);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function generateInverseExponential(payload) {
|
|
60
|
+
const { margin_range, risk_reward, kind, price_places = "%.1f", curveFactor = 2 } = payload;
|
|
61
|
+
const range = Math.abs(margin_range[1] - margin_range[0]);
|
|
62
|
+
return Array.from({ length: risk_reward + 1 }, (_, i) => {
|
|
63
|
+
const t = i / risk_reward;
|
|
64
|
+
const progress = (Math.exp(curveFactor * t) - 1) / (Math.exp(curveFactor) - 1);
|
|
65
|
+
const price = kind === "long" ? margin_range[1] - range * progress : margin_range[0] + range * progress;
|
|
66
|
+
return to_f(price, price_places);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
function getEntries(params) {
|
|
70
|
+
const {
|
|
71
|
+
kind,
|
|
72
|
+
distribution,
|
|
73
|
+
margin_range,
|
|
74
|
+
risk_reward,
|
|
75
|
+
price_places = "%.1f",
|
|
76
|
+
distribution_params = {}
|
|
77
|
+
} = params;
|
|
78
|
+
let entries = [];
|
|
79
|
+
switch (distribution) {
|
|
80
|
+
case "arithmetic":
|
|
81
|
+
entries = generateArithmetic({
|
|
82
|
+
margin_range,
|
|
83
|
+
risk_reward,
|
|
84
|
+
kind,
|
|
85
|
+
price_places,
|
|
86
|
+
percent_change: distribution_params.curveFactor
|
|
87
|
+
});
|
|
88
|
+
break;
|
|
89
|
+
case "geometric":
|
|
90
|
+
entries = generateGeometric({
|
|
91
|
+
margin_range,
|
|
92
|
+
risk_reward,
|
|
93
|
+
kind,
|
|
94
|
+
price_places,
|
|
95
|
+
percent_change: distribution_params.curveFactor
|
|
96
|
+
});
|
|
97
|
+
break;
|
|
98
|
+
case "normal":
|
|
99
|
+
entries = generateNormal({
|
|
100
|
+
margin_range,
|
|
101
|
+
risk_reward,
|
|
102
|
+
kind,
|
|
103
|
+
price_places,
|
|
104
|
+
stdDevFactor: distribution_params.stdDevFactor
|
|
105
|
+
});
|
|
106
|
+
break;
|
|
107
|
+
case "exponential":
|
|
108
|
+
entries = generateExponential({
|
|
109
|
+
margin_range,
|
|
110
|
+
risk_reward,
|
|
111
|
+
kind,
|
|
112
|
+
price_places,
|
|
113
|
+
lambda: distribution_params.lambda
|
|
114
|
+
});
|
|
115
|
+
break;
|
|
116
|
+
case "inverse-exponential":
|
|
117
|
+
entries = generateInverseExponential({
|
|
118
|
+
margin_range,
|
|
119
|
+
risk_reward,
|
|
120
|
+
kind,
|
|
121
|
+
price_places,
|
|
122
|
+
curveFactor: distribution_params.curveFactor
|
|
123
|
+
});
|
|
124
|
+
break;
|
|
125
|
+
default:
|
|
126
|
+
throw new Error(`Unknown distribution type: ${distribution}`);
|
|
127
|
+
}
|
|
128
|
+
return entries.sort((a, b) => a - b);
|
|
129
|
+
}
|
|
130
|
+
var distributions_default = getEntries;
|
|
131
|
+
|
|
1
132
|
// src/helpers/optimizations.ts
|
|
2
133
|
function calculateTheoreticalKelly({
|
|
3
134
|
current_entry,
|
|
@@ -267,6 +398,10 @@ class Signal {
|
|
|
267
398
|
kelly_minimum_risk = 0.2;
|
|
268
399
|
kelly_func = "theoretical";
|
|
269
400
|
symbol;
|
|
401
|
+
distribution = {
|
|
402
|
+
long: "arithmetic",
|
|
403
|
+
short: "geometric"
|
|
404
|
+
};
|
|
270
405
|
constructor({
|
|
271
406
|
focus,
|
|
272
407
|
symbol,
|
|
@@ -293,8 +428,12 @@ class Signal {
|
|
|
293
428
|
kelly_prediction_model = "exponential",
|
|
294
429
|
kelly_confidence_factor = 0.6,
|
|
295
430
|
kelly_minimum_risk = 0.2,
|
|
296
|
-
kelly_func = "theoretical"
|
|
431
|
+
kelly_func = "theoretical",
|
|
432
|
+
full_distribution
|
|
297
433
|
}) {
|
|
434
|
+
if (full_distribution) {
|
|
435
|
+
this.distribution = full_distribution;
|
|
436
|
+
}
|
|
298
437
|
this.symbol = symbol;
|
|
299
438
|
this.minimum_size = minimum_size;
|
|
300
439
|
this.first_order_size = first_order_size;
|
|
@@ -330,7 +469,8 @@ class Signal {
|
|
|
330
469
|
kind = "long",
|
|
331
470
|
risk,
|
|
332
471
|
no_of_trades = 1,
|
|
333
|
-
take_profit
|
|
472
|
+
take_profit,
|
|
473
|
+
distribution
|
|
334
474
|
}) {
|
|
335
475
|
let _stop_loss = stop_loss;
|
|
336
476
|
if (!_stop_loss && stop_percent) {
|
|
@@ -339,16 +479,22 @@ class Signal {
|
|
|
339
479
|
const percent_change = _stop_loss ? Math.max(current_price, _stop_loss) / Math.min(current_price, _stop_loss) - 1 : this.percent_change;
|
|
340
480
|
const _no_of_trades = no_of_trades || this.risk_reward;
|
|
341
481
|
let _resistance = current_price * Math.pow(1 + percent_change, 1);
|
|
482
|
+
const simple_support = Math.min(current_price, stop_loss);
|
|
483
|
+
const simple_resistance = Math.max(current_price, stop_loss);
|
|
342
484
|
const derivedConfig = {
|
|
343
485
|
...this,
|
|
344
486
|
percent_change,
|
|
345
487
|
focus: current_price,
|
|
346
|
-
resistance: _resistance,
|
|
488
|
+
resistance: distribution ? simple_resistance : _resistance,
|
|
347
489
|
risk_per_trade: risk / this.risk_reward,
|
|
348
490
|
minimum_pnl: pnl,
|
|
349
491
|
risk_reward: _no_of_trades,
|
|
350
492
|
take_profit: take_profit || this.take_profit,
|
|
351
|
-
support: kind === "long" ? _stop_loss : this.support
|
|
493
|
+
support: distribution ? simple_support : kind === "long" ? _stop_loss : this.support,
|
|
494
|
+
full_distribution: distribution ? {
|
|
495
|
+
...this.distribution,
|
|
496
|
+
[kind]: distribution
|
|
497
|
+
} : undefined
|
|
352
498
|
};
|
|
353
499
|
const instance = new Signal(derivedConfig);
|
|
354
500
|
if (kind === "short") {}
|
|
@@ -564,12 +710,31 @@ class Signal {
|
|
|
564
710
|
}
|
|
565
711
|
this.zone_risk = original;
|
|
566
712
|
}
|
|
713
|
+
get_future_zones_simple({
|
|
714
|
+
current_price,
|
|
715
|
+
kind = "long",
|
|
716
|
+
raw
|
|
717
|
+
}) {
|
|
718
|
+
const margin_zones = [this.support, this.resistance];
|
|
719
|
+
const distribution = this.distribution ? this.distribution[kind] : "geometric";
|
|
720
|
+
console.log("margin_zones", { margin_zones, distribution });
|
|
721
|
+
let _kind = distribution === "inverse-exponential" ? kind === "long" ? "short" : "long" : kind;
|
|
722
|
+
const entries = distributions_default({
|
|
723
|
+
margin_range: margin_zones,
|
|
724
|
+
kind: _kind,
|
|
725
|
+
distribution,
|
|
726
|
+
risk_reward: this.risk_reward,
|
|
727
|
+
price_places: this.price_places
|
|
728
|
+
});
|
|
729
|
+
return entries.sort((a, b) => a - b);
|
|
730
|
+
}
|
|
567
731
|
get_future_zones({
|
|
568
732
|
current_price,
|
|
569
733
|
kind = "long",
|
|
570
734
|
raw
|
|
571
735
|
}) {
|
|
572
736
|
if (raw) {}
|
|
737
|
+
return this.get_future_zones_simple({ current_price, raw, kind });
|
|
573
738
|
const margin_range = this.get_margin_range(current_price, kind);
|
|
574
739
|
let margin_zones = this.get_margin_zones({ current_price });
|
|
575
740
|
let remaining_zones = margin_zones.filter((x) => JSON.stringify(x) != JSON.stringify(margin_range));
|
|
@@ -1439,7 +1604,9 @@ function buildConfig(app_config, {
|
|
|
1439
1604
|
kelly_confidence_factor = 0.95,
|
|
1440
1605
|
kelly_minimum_risk = 0.2,
|
|
1441
1606
|
kelly_prediction_model = "exponential",
|
|
1442
|
-
kelly_func = "theoretical"
|
|
1607
|
+
kelly_func = "theoretical",
|
|
1608
|
+
min_avg_size = 0,
|
|
1609
|
+
distribution
|
|
1443
1610
|
}) {
|
|
1444
1611
|
let fee = app_config.fee / 100;
|
|
1445
1612
|
let working_risk = risk || app_config.risk_per_trade;
|
|
@@ -1486,9 +1653,12 @@ function buildConfig(app_config, {
|
|
|
1486
1653
|
stop_loss: stop,
|
|
1487
1654
|
risk: working_risk,
|
|
1488
1655
|
kind: kind || app_config.kind,
|
|
1489
|
-
no_of_trades: trade_no
|
|
1656
|
+
no_of_trades: trade_no,
|
|
1657
|
+
distribution
|
|
1490
1658
|
}) || [] : [];
|
|
1491
|
-
|
|
1659
|
+
const new_trades = computeTotalAverageForEachTrade(result, config);
|
|
1660
|
+
let filtered = new_trades.filter((o) => o.avg_size > min_avg_size);
|
|
1661
|
+
return computeTotalAverageForEachTrade(filtered, config);
|
|
1492
1662
|
}
|
|
1493
1663
|
function buildAvg({
|
|
1494
1664
|
_trades,
|
|
@@ -1553,7 +1723,8 @@ function get_app_config_and_max_size(config, payload) {
|
|
|
1553
1723
|
kelly_confidence_factor: payload.kelly_confidence_factor,
|
|
1554
1724
|
kelly_minimum_risk: payload.kelly_minimum_risk,
|
|
1555
1725
|
kelly_prediction_model: payload.kelly_prediction_model,
|
|
1556
|
-
kelly_func: payload.kelly_func
|
|
1726
|
+
kelly_func: payload.kelly_func,
|
|
1727
|
+
distribution: payload.distribution
|
|
1557
1728
|
});
|
|
1558
1729
|
const max_size = initialResult[0]?.avg_size;
|
|
1559
1730
|
const last_value = initialResult[0];
|
|
@@ -1591,7 +1762,8 @@ function buildAppConfig(config, payload) {
|
|
|
1591
1762
|
kelly_confidence_factor: payload.kelly_confidence_factor,
|
|
1592
1763
|
kelly_minimum_risk: payload.kelly_minimum_risk,
|
|
1593
1764
|
kelly_prediction_model: payload.kelly_prediction_model,
|
|
1594
|
-
kelly_func: payload.kelly_func
|
|
1765
|
+
kelly_func: payload.kelly_func,
|
|
1766
|
+
distribution: payload.distribution
|
|
1595
1767
|
});
|
|
1596
1768
|
app_config.max_size = max_size;
|
|
1597
1769
|
app_config.entry = payload.entry || app_config.entry;
|
|
@@ -1608,7 +1780,7 @@ function buildAppConfig(config, payload) {
|
|
|
1608
1780
|
return app_config;
|
|
1609
1781
|
}
|
|
1610
1782
|
function getOptimumStopAndRisk(app_config, params) {
|
|
1611
|
-
const { max_size, target_stop } = params;
|
|
1783
|
+
const { max_size, target_stop, distribution } = params;
|
|
1612
1784
|
const isLong = app_config.kind === "long";
|
|
1613
1785
|
const stopRange = Math.abs(app_config.entry - target_stop) * 0.5;
|
|
1614
1786
|
let low_stop = isLong ? target_stop - stopRange : Math.max(target_stop - stopRange, app_config.entry);
|
|
@@ -1631,7 +1803,8 @@ function getOptimumStopAndRisk(app_config, params) {
|
|
|
1631
1803
|
increase: true,
|
|
1632
1804
|
gap: app_config.gap,
|
|
1633
1805
|
price_places: app_config.price_places,
|
|
1634
|
-
decimal_places: app_config.decimal_places
|
|
1806
|
+
decimal_places: app_config.decimal_places,
|
|
1807
|
+
distribution
|
|
1635
1808
|
});
|
|
1636
1809
|
if (result.length === 0) {
|
|
1637
1810
|
if (isLong) {
|
|
@@ -1685,7 +1858,8 @@ function getOptimumStopAndRisk(app_config, params) {
|
|
|
1685
1858
|
increase: true,
|
|
1686
1859
|
gap: app_config.gap,
|
|
1687
1860
|
price_places: app_config.price_places,
|
|
1688
|
-
decimal_places: app_config.decimal_places
|
|
1861
|
+
decimal_places: app_config.decimal_places,
|
|
1862
|
+
distribution
|
|
1689
1863
|
});
|
|
1690
1864
|
if (result.length === 0) {
|
|
1691
1865
|
high_risk = mid_risk;
|
|
@@ -1730,7 +1904,8 @@ function getOptimumStopAndRisk(app_config, params) {
|
|
|
1730
1904
|
increase: true,
|
|
1731
1905
|
gap: app_config.gap,
|
|
1732
1906
|
price_places: app_config.price_places,
|
|
1733
|
-
decimal_places: app_config.decimal_places
|
|
1907
|
+
decimal_places: app_config.decimal_places,
|
|
1908
|
+
distribution
|
|
1734
1909
|
});
|
|
1735
1910
|
if (result.length === 0)
|
|
1736
1911
|
continue;
|
|
@@ -1853,7 +2028,8 @@ function generateOptimumAppConfig(config, payload, position2) {
|
|
|
1853
2028
|
}, {
|
|
1854
2029
|
entry: payload.entry,
|
|
1855
2030
|
stop: payload.stop,
|
|
1856
|
-
kind: position2.kind
|
|
2031
|
+
kind: position2.kind,
|
|
2032
|
+
distribution: payload.distribution
|
|
1857
2033
|
});
|
|
1858
2034
|
current_app_config.max_size = max_size;
|
|
1859
2035
|
current_app_config.last_value = last_value;
|
|
@@ -1868,7 +2044,8 @@ function generateOptimumAppConfig(config, payload, position2) {
|
|
|
1868
2044
|
increase: true,
|
|
1869
2045
|
gap: current_app_config.gap,
|
|
1870
2046
|
price_places: current_app_config.price_places,
|
|
1871
|
-
decimal_places: current_app_config.decimal_places
|
|
2047
|
+
decimal_places: current_app_config.decimal_places,
|
|
2048
|
+
distribution: payload.distribution
|
|
1872
2049
|
});
|
|
1873
2050
|
if (full_trades.length === 0) {
|
|
1874
2051
|
high_risk = mid_risk;
|
|
@@ -1932,7 +2109,8 @@ function determineOptimumReward(payload) {
|
|
|
1932
2109
|
increase = true,
|
|
1933
2110
|
low_range = 1,
|
|
1934
2111
|
high_range = 199,
|
|
1935
|
-
target_loss
|
|
2112
|
+
target_loss,
|
|
2113
|
+
distribution
|
|
1936
2114
|
} = payload;
|
|
1937
2115
|
const criterion = app_config.strategy || "quantity";
|
|
1938
2116
|
const risk_rewards = createArray(low_range, high_range, 1);
|
|
@@ -1946,7 +2124,8 @@ function determineOptimumReward(payload) {
|
|
|
1946
2124
|
increase,
|
|
1947
2125
|
kind: app_config.kind,
|
|
1948
2126
|
gap: app_config.gap,
|
|
1949
|
-
decimal_places: app_config.decimal_places
|
|
2127
|
+
decimal_places: app_config.decimal_places,
|
|
2128
|
+
distribution
|
|
1950
2129
|
});
|
|
1951
2130
|
let total = 0;
|
|
1952
2131
|
let max = -Infinity;
|
|
@@ -2111,14 +2290,17 @@ function determineOptimumRisk(config, payload, params) {
|
|
|
2111
2290
|
};
|
|
2112
2291
|
}
|
|
2113
2292
|
function computeRiskReward(payload) {
|
|
2114
|
-
const { app_config, entry, stop, risk_per_trade, target_loss } = payload;
|
|
2293
|
+
const { app_config, entry, stop, risk_per_trade, target_loss, distribution } = payload;
|
|
2115
2294
|
const kind = entry > stop ? "long" : "short";
|
|
2116
2295
|
app_config.kind = kind;
|
|
2117
2296
|
app_config.entry = entry;
|
|
2118
2297
|
app_config.stop = stop;
|
|
2119
2298
|
app_config.risk_per_trade = risk_per_trade;
|
|
2120
|
-
const result = determineOptimumReward({
|
|
2121
|
-
|
|
2299
|
+
const result = determineOptimumReward({
|
|
2300
|
+
app_config,
|
|
2301
|
+
target_loss,
|
|
2302
|
+
distribution
|
|
2303
|
+
});
|
|
2122
2304
|
return result;
|
|
2123
2305
|
}
|
|
2124
2306
|
function getRiskReward(payload) {
|
|
@@ -2128,21 +2310,24 @@ function getRiskReward(payload) {
|
|
|
2128
2310
|
risk,
|
|
2129
2311
|
global_config,
|
|
2130
2312
|
force_exact_risk = false,
|
|
2131
|
-
target_loss
|
|
2313
|
+
target_loss,
|
|
2314
|
+
distribution
|
|
2132
2315
|
} = payload;
|
|
2133
2316
|
const { entries, last_value, ...app_config } = buildAppConfig(global_config, {
|
|
2134
2317
|
entry,
|
|
2135
2318
|
stop,
|
|
2136
2319
|
risk_reward: 30,
|
|
2137
2320
|
risk,
|
|
2138
|
-
symbol: global_config.symbol
|
|
2321
|
+
symbol: global_config.symbol,
|
|
2322
|
+
distribution
|
|
2139
2323
|
});
|
|
2140
2324
|
const risk_reward = computeRiskReward({
|
|
2141
2325
|
app_config,
|
|
2142
2326
|
entry,
|
|
2143
2327
|
stop,
|
|
2144
2328
|
risk_per_trade: risk,
|
|
2145
|
-
target_loss
|
|
2329
|
+
target_loss,
|
|
2330
|
+
distribution
|
|
2146
2331
|
});
|
|
2147
2332
|
if (force_exact_risk) {
|
|
2148
2333
|
const new_risk_per_trade = determineOptimumRisk(global_config, {
|
|
@@ -2150,7 +2335,8 @@ function getRiskReward(payload) {
|
|
|
2150
2335
|
stop,
|
|
2151
2336
|
risk_reward,
|
|
2152
2337
|
risk,
|
|
2153
|
-
symbol: global_config.symbol
|
|
2338
|
+
symbol: global_config.symbol,
|
|
2339
|
+
distribution
|
|
2154
2340
|
}, {
|
|
2155
2341
|
highest_risk: risk
|
|
2156
2342
|
}).optimal_risk;
|
|
@@ -2605,7 +2791,7 @@ function constructAppConfig(payload) {
|
|
|
2605
2791
|
kelly_minimum_risk: kelly_config?.kelly_minimum_risk ?? kelly?.kelly_minimum_risk,
|
|
2606
2792
|
kelly_prediction_model: kelly_config?.kelly_prediction_model ?? kelly?.kelly_prediction_model
|
|
2607
2793
|
};
|
|
2608
|
-
const appConfig = buildAppConfig(global_config, options);
|
|
2794
|
+
const { entries: _entries, ...appConfig } = buildAppConfig(global_config, options);
|
|
2609
2795
|
return appConfig;
|
|
2610
2796
|
}
|
|
2611
2797
|
function generateDangerousConfig(payload) {
|