@gbozee/ultimate 0.0.2-32 → 0.0.2-35
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 +281 -0
- package/dist/frontend-index.js +13 -0
- package/dist/index.d.ts +56 -0
- package/dist/index.js +166 -10
- package/package.json +1 -1
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
// Generated by dts-bundle-generator v9.5.1
|
|
2
|
+
|
|
3
|
+
export type SignalConfigType = {
|
|
4
|
+
focus: number;
|
|
5
|
+
budget: number;
|
|
6
|
+
percent_change?: number;
|
|
7
|
+
price_places?: string;
|
|
8
|
+
decimal_places?: string;
|
|
9
|
+
zone_risk?: number;
|
|
10
|
+
fee?: number;
|
|
11
|
+
support?: number;
|
|
12
|
+
risk_reward?: number;
|
|
13
|
+
resistance?: number;
|
|
14
|
+
risk_per_trade?: number;
|
|
15
|
+
increase_size?: boolean;
|
|
16
|
+
additional_increase?: number;
|
|
17
|
+
minimum_pnl?: number;
|
|
18
|
+
take_profit?: number;
|
|
19
|
+
increase_position?: boolean;
|
|
20
|
+
minimum_size?: number;
|
|
21
|
+
first_order_size?: number;
|
|
22
|
+
gap?: number;
|
|
23
|
+
max_size?: number;
|
|
24
|
+
};
|
|
25
|
+
declare class Signal {
|
|
26
|
+
focus: number;
|
|
27
|
+
budget: number;
|
|
28
|
+
percent_change: number;
|
|
29
|
+
price_places: string;
|
|
30
|
+
decimal_places: string;
|
|
31
|
+
zone_risk: number;
|
|
32
|
+
fee: number;
|
|
33
|
+
support?: number;
|
|
34
|
+
risk_reward: number;
|
|
35
|
+
resistance?: number;
|
|
36
|
+
risk_per_trade?: number;
|
|
37
|
+
increase_size: boolean;
|
|
38
|
+
additional_increase: number;
|
|
39
|
+
minimum_pnl: number;
|
|
40
|
+
take_profit?: number;
|
|
41
|
+
increase_position: boolean;
|
|
42
|
+
minimum_size: any;
|
|
43
|
+
first_order_size: number;
|
|
44
|
+
gap: number;
|
|
45
|
+
max_size: number;
|
|
46
|
+
constructor({ focus, 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, }: SignalConfigType);
|
|
47
|
+
build_entry({ current_price, stop_loss, pnl, stop_percent, kind, risk, no_of_trades, take_profit, }: {
|
|
48
|
+
take_profit?: number;
|
|
49
|
+
no_of_trades?: number;
|
|
50
|
+
current_price: number;
|
|
51
|
+
stop_loss?: number;
|
|
52
|
+
kind?: "long" | "short";
|
|
53
|
+
risk: number;
|
|
54
|
+
stop_percent?: number;
|
|
55
|
+
pnl?: number;
|
|
56
|
+
}): any;
|
|
57
|
+
get risk(): number;
|
|
58
|
+
get min_trades(): number;
|
|
59
|
+
get min_price(): number;
|
|
60
|
+
build_opposite_order({ current_price, kind, }: {
|
|
61
|
+
current_price: number;
|
|
62
|
+
kind?: "long" | "short";
|
|
63
|
+
}): any;
|
|
64
|
+
special_build_orders({ current_price, kind, }: {
|
|
65
|
+
current_price: number;
|
|
66
|
+
kind?: "long" | "short";
|
|
67
|
+
}): any;
|
|
68
|
+
build_orders({ current_price, kind, limit, replace_focus, max_index, min_index, }: {
|
|
69
|
+
current_price: number;
|
|
70
|
+
kind?: "long" | "short";
|
|
71
|
+
limit?: boolean;
|
|
72
|
+
replace_focus?: boolean;
|
|
73
|
+
max_index?: number;
|
|
74
|
+
min_index?: number;
|
|
75
|
+
}): any;
|
|
76
|
+
build_orders_old({ current_price, kind, limit, replace_focus, max_index, min_index, }: {
|
|
77
|
+
current_price: number;
|
|
78
|
+
kind?: "long" | "short";
|
|
79
|
+
limit?: boolean;
|
|
80
|
+
replace_focus?: boolean;
|
|
81
|
+
max_index?: number;
|
|
82
|
+
min_index?: number;
|
|
83
|
+
}): any;
|
|
84
|
+
get_bulk_trade_zones({ current_price, kind, limit, }: {
|
|
85
|
+
current_price: number;
|
|
86
|
+
kind?: "long" | "short";
|
|
87
|
+
limit?: boolean;
|
|
88
|
+
}): any;
|
|
89
|
+
get_future_zones({ current_price, kind, raw, }: {
|
|
90
|
+
raw?: boolean;
|
|
91
|
+
current_price: number;
|
|
92
|
+
kind?: "long" | "short";
|
|
93
|
+
}): number[];
|
|
94
|
+
to_f(value: number, places?: string): number;
|
|
95
|
+
get_margin_zones({ current_price, kind, }: {
|
|
96
|
+
current_price: number;
|
|
97
|
+
kind?: "long" | "short";
|
|
98
|
+
}): number[][];
|
|
99
|
+
get_margin_range(current_price: number, kind?: string): number[];
|
|
100
|
+
process_orders({ current_price, stop_loss, trade_zones, kind, }: {
|
|
101
|
+
current_price: number;
|
|
102
|
+
stop_loss: number;
|
|
103
|
+
trade_zones: number[];
|
|
104
|
+
kind?: "long" | "short";
|
|
105
|
+
}): any[];
|
|
106
|
+
get_risk_per_trade(number_of_orders: number): number;
|
|
107
|
+
build_trade_dict({ entry, stop, risk, arr, index, new_fees, kind, start, take_profit, }: {
|
|
108
|
+
entry: number;
|
|
109
|
+
stop: number;
|
|
110
|
+
risk: number;
|
|
111
|
+
arr: number[];
|
|
112
|
+
index: number;
|
|
113
|
+
new_fees?: number;
|
|
114
|
+
kind?: "long" | "short";
|
|
115
|
+
start?: number;
|
|
116
|
+
take_profit?: number;
|
|
117
|
+
}): {
|
|
118
|
+
entry: number;
|
|
119
|
+
risk: number;
|
|
120
|
+
quantity: number;
|
|
121
|
+
sell_price: number;
|
|
122
|
+
risk_sell: number;
|
|
123
|
+
stop: number;
|
|
124
|
+
pnl: number;
|
|
125
|
+
fee: number;
|
|
126
|
+
net: number;
|
|
127
|
+
incurred: number;
|
|
128
|
+
stop_percent: number;
|
|
129
|
+
};
|
|
130
|
+
to_df(currentPrice: number, places?: string): number;
|
|
131
|
+
}
|
|
132
|
+
export type GlobalConfig = {
|
|
133
|
+
profit_percent: number;
|
|
134
|
+
symbol: string;
|
|
135
|
+
profit: number;
|
|
136
|
+
risk: number;
|
|
137
|
+
stop_percent: number;
|
|
138
|
+
kind: "long" | "short";
|
|
139
|
+
reduce_percent: number;
|
|
140
|
+
support: number;
|
|
141
|
+
resistance: number;
|
|
142
|
+
price_places: string;
|
|
143
|
+
decimal_places: string;
|
|
144
|
+
min_size: number;
|
|
145
|
+
accounts: {
|
|
146
|
+
owner: string;
|
|
147
|
+
exchange?: string;
|
|
148
|
+
}[];
|
|
149
|
+
risk_reward: number;
|
|
150
|
+
reverse_factor: number;
|
|
151
|
+
};
|
|
152
|
+
export declare function determine_average_entry_and_size(orders: Array<{
|
|
153
|
+
price: number;
|
|
154
|
+
quantity: number;
|
|
155
|
+
}>, places?: string, price_places?: string): {
|
|
156
|
+
entry: number;
|
|
157
|
+
price: number;
|
|
158
|
+
quantity: number;
|
|
159
|
+
};
|
|
160
|
+
export declare const createArray: (start: number, stop: number, step: number) => number[];
|
|
161
|
+
export type AppConfig = {
|
|
162
|
+
fee: number;
|
|
163
|
+
risk_per_trade: number;
|
|
164
|
+
risk_reward: number;
|
|
165
|
+
symbol?: string;
|
|
166
|
+
focus: number;
|
|
167
|
+
budget: number;
|
|
168
|
+
support: number;
|
|
169
|
+
resistance: number;
|
|
170
|
+
percent_change: number;
|
|
171
|
+
tradeSplit?: number;
|
|
172
|
+
take_profit?: number;
|
|
173
|
+
kind: "long" | "short";
|
|
174
|
+
entry: number;
|
|
175
|
+
stop: number;
|
|
176
|
+
min_size: number;
|
|
177
|
+
price_places?: string;
|
|
178
|
+
strategy?: "quantity" | "entry";
|
|
179
|
+
as_array?: boolean;
|
|
180
|
+
decimal_places?: string;
|
|
181
|
+
min_profit?: number;
|
|
182
|
+
raw?: boolean;
|
|
183
|
+
gap?: number;
|
|
184
|
+
rr?: number;
|
|
185
|
+
max_size?: number;
|
|
186
|
+
last_value?: any;
|
|
187
|
+
entries?: any[];
|
|
188
|
+
};
|
|
189
|
+
export type ExtendConfigType = {
|
|
190
|
+
take_profit?: number;
|
|
191
|
+
entry: number;
|
|
192
|
+
risk?: number;
|
|
193
|
+
stop?: number;
|
|
194
|
+
risk_reward?: number;
|
|
195
|
+
raw_instance?: boolean;
|
|
196
|
+
no_of_trades?: number;
|
|
197
|
+
increase?: boolean;
|
|
198
|
+
price_places?: string;
|
|
199
|
+
decimal_places?: string;
|
|
200
|
+
min_profit?: number;
|
|
201
|
+
kind?: "long" | "short";
|
|
202
|
+
gap?: number;
|
|
203
|
+
rr?: number;
|
|
204
|
+
};
|
|
205
|
+
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, }: ExtendConfigType): any[] | Signal;
|
|
206
|
+
export declare function buildAvg({ _trades, kind, }: {
|
|
207
|
+
_trades: any[];
|
|
208
|
+
kind: "long" | "short";
|
|
209
|
+
}): any;
|
|
210
|
+
export declare function sortedBuildConfig(app_config: AppConfig, options: any): any[];
|
|
211
|
+
export declare function get_app_config_and_max_size(config: GlobalConfig, payload: {
|
|
212
|
+
entry: number;
|
|
213
|
+
stop: number;
|
|
214
|
+
kind: "long" | "short";
|
|
215
|
+
}): {
|
|
216
|
+
app_config: AppConfig;
|
|
217
|
+
max_size: any;
|
|
218
|
+
last_value: any;
|
|
219
|
+
entries: {
|
|
220
|
+
entry: any;
|
|
221
|
+
avg_entry: any;
|
|
222
|
+
avg_size: any;
|
|
223
|
+
neg_pnl: any;
|
|
224
|
+
quantity: any;
|
|
225
|
+
}[];
|
|
226
|
+
};
|
|
227
|
+
export declare function buildAppConfig(config: GlobalConfig, payload: {
|
|
228
|
+
entry: number;
|
|
229
|
+
stop: number;
|
|
230
|
+
risk_reward: number;
|
|
231
|
+
risk: number;
|
|
232
|
+
symbol: string;
|
|
233
|
+
profit?: number;
|
|
234
|
+
}): AppConfig;
|
|
235
|
+
export declare function getOptimumStopAndRisk(app_config: AppConfig, params: {
|
|
236
|
+
max_size: number;
|
|
237
|
+
target_stop: number;
|
|
238
|
+
highest_risk?: number;
|
|
239
|
+
}): {
|
|
240
|
+
optimal_stop: number;
|
|
241
|
+
optimal_risk: number;
|
|
242
|
+
avg_size: any;
|
|
243
|
+
avg_entry: any;
|
|
244
|
+
result: any[];
|
|
245
|
+
first_entry: any;
|
|
246
|
+
neg_pnl: any;
|
|
247
|
+
risk_reward: number;
|
|
248
|
+
size_diff: number;
|
|
249
|
+
entry_diff: number;
|
|
250
|
+
};
|
|
251
|
+
export declare function generate_config_params(app_config: AppConfig, payload: {
|
|
252
|
+
entry: number;
|
|
253
|
+
stop: number;
|
|
254
|
+
risk_reward: number;
|
|
255
|
+
risk: number;
|
|
256
|
+
symbol: string;
|
|
257
|
+
}): {
|
|
258
|
+
entry: number;
|
|
259
|
+
stop: number;
|
|
260
|
+
avg_size: any;
|
|
261
|
+
avg_entry: any;
|
|
262
|
+
risk_reward: number;
|
|
263
|
+
neg_pnl: any;
|
|
264
|
+
risk: number;
|
|
265
|
+
};
|
|
266
|
+
export declare function determine_break_even_price(payload: {
|
|
267
|
+
long_position: {
|
|
268
|
+
entry: number;
|
|
269
|
+
quantity: number;
|
|
270
|
+
};
|
|
271
|
+
short_position: {
|
|
272
|
+
entry: number;
|
|
273
|
+
quantity: number;
|
|
274
|
+
};
|
|
275
|
+
fee_percent?: number;
|
|
276
|
+
}): {
|
|
277
|
+
price: number;
|
|
278
|
+
direction: string;
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
export {};
|
package/dist/frontend-index.js
CHANGED
|
@@ -1305,11 +1305,24 @@ function generate_config_params(app_config, payload) {
|
|
|
1305
1305
|
risk: payload.risk
|
|
1306
1306
|
};
|
|
1307
1307
|
}
|
|
1308
|
+
function determine_break_even_price(payload) {
|
|
1309
|
+
const { long_position, short_position, fee_percent = 0.05 / 100 } = payload;
|
|
1310
|
+
const long_notional = long_position.entry * long_position.quantity;
|
|
1311
|
+
const short_notional = short_position.entry * short_position.quantity;
|
|
1312
|
+
const net_quantity = long_position.quantity - short_position.quantity;
|
|
1313
|
+
const net_capital = Math.abs(long_notional - short_notional);
|
|
1314
|
+
const break_even_price = net_capital / (Math.abs(net_quantity) + fee_percent * Math.abs(net_quantity));
|
|
1315
|
+
return {
|
|
1316
|
+
price: break_even_price,
|
|
1317
|
+
direction: net_quantity > 0 ? "long" : "short"
|
|
1318
|
+
};
|
|
1319
|
+
}
|
|
1308
1320
|
export {
|
|
1309
1321
|
sortedBuildConfig,
|
|
1310
1322
|
get_app_config_and_max_size,
|
|
1311
1323
|
getOptimumStopAndRisk,
|
|
1312
1324
|
generate_config_params,
|
|
1325
|
+
determine_break_even_price,
|
|
1313
1326
|
determine_average_entry_and_size,
|
|
1314
1327
|
createArray,
|
|
1315
1328
|
buildConfig,
|
package/dist/index.d.ts
CHANGED
|
@@ -183,6 +183,13 @@ export interface BaseExchange {
|
|
|
183
183
|
asset: string;
|
|
184
184
|
amount: number;
|
|
185
185
|
}): Promise<any>;
|
|
186
|
+
placeMarketOrder(payload: {
|
|
187
|
+
symbol: string;
|
|
188
|
+
kind: "long" | "short";
|
|
189
|
+
quantity: number;
|
|
190
|
+
price_places?: string;
|
|
191
|
+
decimal_places?: string;
|
|
192
|
+
}): Promise<any>;
|
|
186
193
|
}
|
|
187
194
|
export interface BaseSystemFields {
|
|
188
195
|
id: string;
|
|
@@ -410,6 +417,11 @@ export declare class AppDatabase {
|
|
|
410
417
|
}>;
|
|
411
418
|
getMoverExchangeInstances(): Promise<ExchangeAccount[]>;
|
|
412
419
|
updateScheduledTrade(id: string, payload: any): Promise<import("pocketbase").RecordModel>;
|
|
420
|
+
getPositionsToAutoFollow(): Promise<(Position$1 & {
|
|
421
|
+
expand: {
|
|
422
|
+
account: ExchangeAccount;
|
|
423
|
+
};
|
|
424
|
+
})[]>;
|
|
413
425
|
createOrUpdatePositionConfig(db_position: any, payload: {
|
|
414
426
|
entry: number;
|
|
415
427
|
stop: number;
|
|
@@ -709,6 +721,20 @@ export declare function generate_config_params(app_config: AppConfig, payload: {
|
|
|
709
721
|
neg_pnl: any;
|
|
710
722
|
risk: number;
|
|
711
723
|
};
|
|
724
|
+
export declare function determine_break_even_price(payload: {
|
|
725
|
+
long_position: {
|
|
726
|
+
entry: number;
|
|
727
|
+
quantity: number;
|
|
728
|
+
};
|
|
729
|
+
short_position: {
|
|
730
|
+
entry: number;
|
|
731
|
+
quantity: number;
|
|
732
|
+
};
|
|
733
|
+
fee_percent?: number;
|
|
734
|
+
}): {
|
|
735
|
+
price: number;
|
|
736
|
+
direction: string;
|
|
737
|
+
};
|
|
712
738
|
declare class ExchangeAccount$1 {
|
|
713
739
|
private instance;
|
|
714
740
|
exchange: BaseExchange;
|
|
@@ -793,6 +819,12 @@ declare class ExchangeAccount$1 {
|
|
|
793
819
|
symbol: string;
|
|
794
820
|
orders: number[];
|
|
795
821
|
}): Promise<any>;
|
|
822
|
+
getBreakEvenPrice(payload: {
|
|
823
|
+
symbol: string;
|
|
824
|
+
}): Promise<{
|
|
825
|
+
price: number;
|
|
826
|
+
direction: string;
|
|
827
|
+
}>;
|
|
796
828
|
buildAppConfig(payload: {
|
|
797
829
|
entry: number;
|
|
798
830
|
stop: number;
|
|
@@ -803,6 +835,17 @@ declare class ExchangeAccount$1 {
|
|
|
803
835
|
update_db?: boolean;
|
|
804
836
|
profit_percent?: number;
|
|
805
837
|
}): Promise<AppConfig>;
|
|
838
|
+
buildTrades(payload: {
|
|
839
|
+
symbol: string;
|
|
840
|
+
kind: "long" | "short";
|
|
841
|
+
risk?: number;
|
|
842
|
+
}): Promise<{
|
|
843
|
+
trades: any[];
|
|
844
|
+
max_size: any;
|
|
845
|
+
last_price: any;
|
|
846
|
+
total_size: number;
|
|
847
|
+
avg_entry: number;
|
|
848
|
+
}>;
|
|
806
849
|
placeConfigOrders(app_config: AppConfig, solution: {
|
|
807
850
|
risk_reward: number;
|
|
808
851
|
entry: number;
|
|
@@ -837,9 +880,11 @@ declare class ExchangeAccount$1 {
|
|
|
837
880
|
determineAmountToBuy(payload: {
|
|
838
881
|
orders: any[];
|
|
839
882
|
kind: "long" | "short";
|
|
883
|
+
refresh?: boolean;
|
|
840
884
|
decimal_places?: string;
|
|
841
885
|
price_places?: string;
|
|
842
886
|
symbol: string;
|
|
887
|
+
cancel?: boolean;
|
|
843
888
|
place?: boolean;
|
|
844
889
|
}): Promise<any[]>;
|
|
845
890
|
placeSharedOrder(action: "place_limit_orders" | "place_stop_orders" | "place_tp_orders", payload: {
|
|
@@ -962,6 +1007,15 @@ declare class ExchangeAccount$1 {
|
|
|
962
1007
|
risk_reward?: number;
|
|
963
1008
|
risk?: number;
|
|
964
1009
|
}): Promise<any>;
|
|
1010
|
+
placeMarketOrder(payload: {
|
|
1011
|
+
symbol: string;
|
|
1012
|
+
kind: "long" | "short";
|
|
1013
|
+
quantity: number;
|
|
1014
|
+
}): Promise<void>;
|
|
1015
|
+
placeSingleOrder(payload: {
|
|
1016
|
+
symbol: string;
|
|
1017
|
+
kind: "long" | "short";
|
|
1018
|
+
}): Promise<string>;
|
|
965
1019
|
triggerTradeFromConfig(payload: {
|
|
966
1020
|
symbol: string;
|
|
967
1021
|
kind: "long" | "short";
|
|
@@ -969,6 +1023,7 @@ declare class ExchangeAccount$1 {
|
|
|
969
1023
|
raw?: boolean;
|
|
970
1024
|
tp?: boolean;
|
|
971
1025
|
stop?: boolean;
|
|
1026
|
+
use_current?: boolean;
|
|
972
1027
|
}): Promise<any>;
|
|
973
1028
|
verifyStopLoss(payload: {
|
|
974
1029
|
symbol: string;
|
|
@@ -1148,6 +1203,7 @@ declare class App {
|
|
|
1148
1203
|
refreshAllPositionsWithSymbol(payload: {
|
|
1149
1204
|
symbol: string;
|
|
1150
1205
|
}): Promise<void>;
|
|
1206
|
+
autoFollowPositions(): Promise<void>;
|
|
1151
1207
|
getMoverExchangeInstances(): Promise<ExchangeAccount[]>;
|
|
1152
1208
|
updateTpOnAllMarkets(): Promise<void>;
|
|
1153
1209
|
triggerMoverTask(payload: {
|
package/dist/index.js
CHANGED
|
@@ -32491,6 +32491,13 @@ class AppDatabase {
|
|
|
32491
32491
|
async updateScheduledTrade(id, payload) {
|
|
32492
32492
|
return await this.pb.collection("scheduled_trades").update(id, payload);
|
|
32493
32493
|
}
|
|
32494
|
+
async getPositionsToAutoFollow() {
|
|
32495
|
+
const result = await this.pb.collection("positions").getFullList({
|
|
32496
|
+
filter: `follow=true`,
|
|
32497
|
+
expand: "account"
|
|
32498
|
+
});
|
|
32499
|
+
return result;
|
|
32500
|
+
}
|
|
32494
32501
|
async createOrUpdatePositionConfig(db_position, payload) {
|
|
32495
32502
|
let config = null;
|
|
32496
32503
|
if (db_position.config) {
|
|
@@ -34835,6 +34842,19 @@ class BinanceExchange {
|
|
|
34835
34842
|
return result;
|
|
34836
34843
|
}
|
|
34837
34844
|
}
|
|
34845
|
+
async placeMarketOrder(payload) {
|
|
34846
|
+
const { symbol, kind, quantity, price_places, decimal_places } = payload;
|
|
34847
|
+
const currentPrice = await this.get_current_price(symbol);
|
|
34848
|
+
return createLimitPurchaseOrders(this.client, symbol, price_places, decimal_places, [
|
|
34849
|
+
{
|
|
34850
|
+
force_market: true,
|
|
34851
|
+
side: kind === "long" ? "buy" : "sell",
|
|
34852
|
+
kind,
|
|
34853
|
+
quantity,
|
|
34854
|
+
price: currentPrice
|
|
34855
|
+
}
|
|
34856
|
+
]);
|
|
34857
|
+
}
|
|
34838
34858
|
}
|
|
34839
34859
|
function getPricePlaces(target) {
|
|
34840
34860
|
const numStr = target.toString();
|
|
@@ -35507,6 +35527,8 @@ class BybitExchange {
|
|
|
35507
35527
|
}
|
|
35508
35528
|
async crossAccountTransfer(payload) {
|
|
35509
35529
|
}
|
|
35530
|
+
async placeMarketOrder(payload) {
|
|
35531
|
+
}
|
|
35510
35532
|
}
|
|
35511
35533
|
|
|
35512
35534
|
// src/helpers/accounts.ts
|
|
@@ -36190,6 +36212,18 @@ function generate_config_params(app_config, payload) {
|
|
|
36190
36212
|
risk: payload.risk
|
|
36191
36213
|
};
|
|
36192
36214
|
}
|
|
36215
|
+
function determine_break_even_price(payload) {
|
|
36216
|
+
const { long_position, short_position, fee_percent = 0.05 / 100 } = payload;
|
|
36217
|
+
const long_notional = long_position.entry * long_position.quantity;
|
|
36218
|
+
const short_notional = short_position.entry * short_position.quantity;
|
|
36219
|
+
const net_quantity = long_position.quantity - short_position.quantity;
|
|
36220
|
+
const net_capital = Math.abs(long_notional - short_notional);
|
|
36221
|
+
const break_even_price = net_capital / (Math.abs(net_quantity) + fee_percent * Math.abs(net_quantity));
|
|
36222
|
+
return {
|
|
36223
|
+
price: break_even_price,
|
|
36224
|
+
direction: net_quantity > 0 ? "long" : "short"
|
|
36225
|
+
};
|
|
36226
|
+
}
|
|
36193
36227
|
|
|
36194
36228
|
// src/exchange-account.ts
|
|
36195
36229
|
class ExchangeAccount {
|
|
@@ -36371,6 +36405,18 @@ class ExchangeAccount {
|
|
|
36371
36405
|
async cancelExchangeOrders(payload) {
|
|
36372
36406
|
return this.exchange.cancelOrders(payload);
|
|
36373
36407
|
}
|
|
36408
|
+
async getBreakEvenPrice(payload) {
|
|
36409
|
+
const positions = await this.syncAccount({
|
|
36410
|
+
symbol: payload.symbol
|
|
36411
|
+
});
|
|
36412
|
+
const long_position = positions.find((x) => x.kind === "long");
|
|
36413
|
+
const short_position = positions.find((x) => x.kind === "short");
|
|
36414
|
+
const break_even_price = determine_break_even_price({
|
|
36415
|
+
long_position,
|
|
36416
|
+
short_position
|
|
36417
|
+
});
|
|
36418
|
+
return break_even_price;
|
|
36419
|
+
}
|
|
36374
36420
|
async buildAppConfig(payload) {
|
|
36375
36421
|
let config = await this.app_db.getSymbolConfigFromDB(payload.symbol);
|
|
36376
36422
|
const app_config = buildAppConfig(config, payload);
|
|
@@ -36391,6 +36437,58 @@ class ExchangeAccount {
|
|
|
36391
36437
|
}
|
|
36392
36438
|
return app_config;
|
|
36393
36439
|
}
|
|
36440
|
+
async buildTrades(payload) {
|
|
36441
|
+
const { symbol, kind, risk } = payload;
|
|
36442
|
+
const config = await this.getPositionConfig({
|
|
36443
|
+
symbol,
|
|
36444
|
+
kind
|
|
36445
|
+
});
|
|
36446
|
+
const app_config = await this.buildAppConfig({
|
|
36447
|
+
entry: config.entry,
|
|
36448
|
+
stop: config.stop,
|
|
36449
|
+
risk_reward: config.risk_reward,
|
|
36450
|
+
risk: risk || config.risk,
|
|
36451
|
+
symbol
|
|
36452
|
+
});
|
|
36453
|
+
const { trades } = await this.placeConfigOrders(app_config, {
|
|
36454
|
+
risk_reward: config.risk_reward,
|
|
36455
|
+
entry: config.entry,
|
|
36456
|
+
stop: config.stop,
|
|
36457
|
+
risk_per_trade: risk || config.risk,
|
|
36458
|
+
avg_size: 0,
|
|
36459
|
+
neg_pnl: 0,
|
|
36460
|
+
min_size: app_config.min_size,
|
|
36461
|
+
symbol
|
|
36462
|
+
});
|
|
36463
|
+
const position2 = await this.syncAccount({
|
|
36464
|
+
symbol,
|
|
36465
|
+
kind
|
|
36466
|
+
});
|
|
36467
|
+
const orders_to_place = await this.determineAmountToBuy({
|
|
36468
|
+
orders: trades.map((x) => ({
|
|
36469
|
+
entry: x.entry,
|
|
36470
|
+
quantity: x.quantity
|
|
36471
|
+
})),
|
|
36472
|
+
kind,
|
|
36473
|
+
decimal_places: app_config.decimal_places,
|
|
36474
|
+
price_places: app_config.price_places,
|
|
36475
|
+
symbol
|
|
36476
|
+
});
|
|
36477
|
+
const avg_values = determine_average_entry_and_size(orders_to_place.map((u) => ({
|
|
36478
|
+
price: u.entry,
|
|
36479
|
+
quantity: u.quantity
|
|
36480
|
+
})).concat({
|
|
36481
|
+
price: position2.entry,
|
|
36482
|
+
quantity: position2.quantity
|
|
36483
|
+
}), app_config.decimal_places, app_config.price_places);
|
|
36484
|
+
return {
|
|
36485
|
+
trades: orders_to_place,
|
|
36486
|
+
max_size: trades[0].avg_size,
|
|
36487
|
+
last_price: trades[0].entry,
|
|
36488
|
+
total_size: avg_values.quantity,
|
|
36489
|
+
avg_entry: avg_values.price
|
|
36490
|
+
};
|
|
36491
|
+
}
|
|
36394
36492
|
async placeConfigOrders(app_config, solution, place, skip_stop) {
|
|
36395
36493
|
app_config.entry = solution.entry;
|
|
36396
36494
|
app_config.stop = solution.stop;
|
|
@@ -36466,7 +36564,14 @@ class ExchangeAccount {
|
|
|
36466
36564
|
};
|
|
36467
36565
|
}
|
|
36468
36566
|
async determineAmountToBuy(payload) {
|
|
36469
|
-
const {
|
|
36567
|
+
const {
|
|
36568
|
+
orders,
|
|
36569
|
+
kind,
|
|
36570
|
+
decimal_places = "%.3f",
|
|
36571
|
+
symbol,
|
|
36572
|
+
refresh,
|
|
36573
|
+
cancel
|
|
36574
|
+
} = payload;
|
|
36470
36575
|
const totalQuantity = orders.reduce((sum, order) => sum + (order.quantity || 0), 0);
|
|
36471
36576
|
let runningTotal = to_f(totalQuantity, decimal_places);
|
|
36472
36577
|
let sortedOrders = [...orders].sort((a, b) => (a.entry || 0) - (b.entry || 0));
|
|
@@ -36485,7 +36590,7 @@ class ExchangeAccount {
|
|
|
36485
36590
|
const position2 = await this.syncAccount({
|
|
36486
36591
|
symbol,
|
|
36487
36592
|
kind,
|
|
36488
|
-
live_refresh:
|
|
36593
|
+
live_refresh: refresh,
|
|
36489
36594
|
update: true
|
|
36490
36595
|
});
|
|
36491
36596
|
let existingOrders = await this.syncOrders({
|
|
@@ -36502,7 +36607,7 @@ class ExchangeAccount {
|
|
|
36502
36607
|
filteredOrders = filteredOrders.filter((k) => !existingOrders.map((j) => j.price).includes(k.price));
|
|
36503
36608
|
const side = kind.toLowerCase() === "long" ? "buy" : "sell";
|
|
36504
36609
|
const shouldCancel = existingOrders.filter((k) => !orders.map((j) => j.entry).includes(k.price) && k.side === side).map((u) => u.price);
|
|
36505
|
-
if (shouldCancel.length > 0) {
|
|
36610
|
+
if (shouldCancel.length > 0 && cancel) {
|
|
36506
36611
|
const pp = kind === "long" ? Math.max(...shouldCancel) : Math.min(...shouldCancel);
|
|
36507
36612
|
const cancel_orders = await this.cancelOrders({
|
|
36508
36613
|
symbol,
|
|
@@ -36924,8 +37029,44 @@ class ExchangeAccount {
|
|
|
36924
37029
|
}
|
|
36925
37030
|
return null;
|
|
36926
37031
|
}
|
|
37032
|
+
async placeMarketOrder(payload) {
|
|
37033
|
+
const { symbol, kind, quantity } = payload;
|
|
37034
|
+
const symbol_config = await this.recomputeSymbolConfig({
|
|
37035
|
+
symbol
|
|
37036
|
+
});
|
|
37037
|
+
await this.exchange.placeMarketOrder({
|
|
37038
|
+
symbol,
|
|
37039
|
+
kind,
|
|
37040
|
+
quantity,
|
|
37041
|
+
price_places: symbol_config.price_places,
|
|
37042
|
+
decimal_places: symbol_config.decimal_places
|
|
37043
|
+
});
|
|
37044
|
+
}
|
|
37045
|
+
async placeSingleOrder(payload) {
|
|
37046
|
+
const { symbol, kind } = payload;
|
|
37047
|
+
const positions = await this.syncAccount({
|
|
37048
|
+
live_refresh: true,
|
|
37049
|
+
update: true,
|
|
37050
|
+
symbol
|
|
37051
|
+
});
|
|
37052
|
+
const long_position = positions.find((x) => x.kind === "long");
|
|
37053
|
+
const short_position = positions.find((x) => x.kind === "short");
|
|
37054
|
+
const focus_position = kind === "long" ? long_position : short_position;
|
|
37055
|
+
const track_position = kind === "long" ? short_position : long_position;
|
|
37056
|
+
if (!focus_position.follow) {
|
|
37057
|
+
return "No follow set";
|
|
37058
|
+
}
|
|
37059
|
+
if (track_position.quantity !== focus_position.quantity && focus_position.quantity < track_position.quantity) {
|
|
37060
|
+
const remaining_quantity = Math.abs(track_position.quantity - focus_position.quantity);
|
|
37061
|
+
await this.placeMarketOrder({
|
|
37062
|
+
symbol,
|
|
37063
|
+
kind,
|
|
37064
|
+
quantity: remaining_quantity
|
|
37065
|
+
});
|
|
37066
|
+
}
|
|
37067
|
+
}
|
|
36927
37068
|
async triggerTradeFromConfig(payload) {
|
|
36928
|
-
const { symbol, kind, place = true, stop } = payload;
|
|
37069
|
+
const { symbol, kind, place = true, stop, use_current } = payload;
|
|
36929
37070
|
const position2 = await this.syncAccount({
|
|
36930
37071
|
symbol,
|
|
36931
37072
|
kind
|
|
@@ -36942,7 +37083,7 @@ class ExchangeAccount {
|
|
|
36942
37083
|
risk: config.risk,
|
|
36943
37084
|
place,
|
|
36944
37085
|
raw: payload.raw,
|
|
36945
|
-
use_current
|
|
37086
|
+
use_current
|
|
36946
37087
|
});
|
|
36947
37088
|
}
|
|
36948
37089
|
}
|
|
@@ -38074,15 +38215,29 @@ class App {
|
|
|
38074
38215
|
owner: exchange.owner,
|
|
38075
38216
|
exchange: exchange.exchange
|
|
38076
38217
|
});
|
|
38077
|
-
await exchange_account.
|
|
38218
|
+
await exchange_account.placeProfitAndStop({
|
|
38078
38219
|
symbol,
|
|
38079
|
-
|
|
38080
|
-
|
|
38220
|
+
trigger: true,
|
|
38221
|
+
refresh: true
|
|
38081
38222
|
});
|
|
38082
|
-
await exchange_account.
|
|
38223
|
+
await exchange_account.syncAccount({
|
|
38083
38224
|
symbol,
|
|
38084
|
-
|
|
38225
|
+
update: true
|
|
38226
|
+
});
|
|
38227
|
+
}
|
|
38228
|
+
}
|
|
38229
|
+
async autoFollowPositions() {
|
|
38230
|
+
const positions = await this.app_db.getPositionsToAutoFollow();
|
|
38231
|
+
for (const position2 of positions) {
|
|
38232
|
+
const account = position2.expand.account;
|
|
38233
|
+
console.log("Getting account for ", account.owner, account.exchange);
|
|
38234
|
+
const exchange_account = await this.getExchangeAccount(account);
|
|
38235
|
+
console.log("Placing follow order for ", position2.symbol);
|
|
38236
|
+
const result = await exchange_account.placeSingleOrder({
|
|
38237
|
+
symbol: position2.symbol,
|
|
38238
|
+
kind: position2.kind
|
|
38085
38239
|
});
|
|
38240
|
+
console.log("result", result);
|
|
38086
38241
|
}
|
|
38087
38242
|
}
|
|
38088
38243
|
async getMoverExchangeInstances() {
|
|
@@ -38241,6 +38396,7 @@ export {
|
|
|
38241
38396
|
get_app_config_and_max_size,
|
|
38242
38397
|
getOptimumStopAndRisk,
|
|
38243
38398
|
generate_config_params,
|
|
38399
|
+
determine_break_even_price,
|
|
38244
38400
|
determine_average_entry_and_size,
|
|
38245
38401
|
createArray,
|
|
38246
38402
|
buildConfig,
|