@gbozee/ultimate 0.0.2-113 → 0.0.2-114
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/index.cjs +334 -349
- package/dist/index.d.ts +91 -16
- package/dist/index.js +334 -349
- package/dist/mcp-server.cjs +334 -349
- package/dist/mcp-server.js +334 -349
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -54773,13 +54773,207 @@ class Strategy {
|
|
|
54773
54773
|
|
|
54774
54774
|
// src/exchanges/binance.ts
|
|
54775
54775
|
var import_binance = __toESM(require_lib2());
|
|
54776
|
-
|
|
54777
54776
|
// src/types/index.ts
|
|
54778
54777
|
class BaseExchange {
|
|
54779
54778
|
client;
|
|
54779
|
+
getCredentials;
|
|
54780
|
+
proxyAgent;
|
|
54780
54781
|
constructor(client) {
|
|
54781
54782
|
this.client = client;
|
|
54782
54783
|
}
|
|
54784
|
+
async rawCreateLimitPurchaseOrders(payload) {
|
|
54785
|
+
const { symbol, orders, price_places, decimal_places } = payload;
|
|
54786
|
+
return this._createLimitPurchaseOrders({
|
|
54787
|
+
symbol,
|
|
54788
|
+
price_places,
|
|
54789
|
+
decimal_places,
|
|
54790
|
+
orders
|
|
54791
|
+
});
|
|
54792
|
+
}
|
|
54793
|
+
async placeStopOrders(payload) {
|
|
54794
|
+
if (payload.place) {
|
|
54795
|
+
const current_price = await this.getCurrentPrice(payload.symbol);
|
|
54796
|
+
return this._placeStopOrder({
|
|
54797
|
+
symbol: payload.symbol,
|
|
54798
|
+
stop: payload.stop,
|
|
54799
|
+
final_stop: payload.stop,
|
|
54800
|
+
quantity: Math.abs(payload.quantity),
|
|
54801
|
+
kind: payload.kind,
|
|
54802
|
+
cancel: true,
|
|
54803
|
+
is_limit: true,
|
|
54804
|
+
price_places: payload.price_places,
|
|
54805
|
+
decimal_places: payload.decimal_places,
|
|
54806
|
+
current_price
|
|
54807
|
+
});
|
|
54808
|
+
}
|
|
54809
|
+
}
|
|
54810
|
+
async bulkPlaceLimitOrders(payload) {
|
|
54811
|
+
const {
|
|
54812
|
+
orders,
|
|
54813
|
+
kind,
|
|
54814
|
+
decimal_places = "%.3f",
|
|
54815
|
+
price_places = "%.1f",
|
|
54816
|
+
symbol,
|
|
54817
|
+
place = false
|
|
54818
|
+
} = payload;
|
|
54819
|
+
const totalQuantity = orders.reduce((sum, order) => sum + (order.quantity || 0), 0);
|
|
54820
|
+
let runningTotal = to_f2(totalQuantity, decimal_places);
|
|
54821
|
+
let sortedOrders = [...orders].sort((a, b) => (a.entry || 0) - (b.entry || 0));
|
|
54822
|
+
if (kind === "short") {
|
|
54823
|
+
sortedOrders.reverse();
|
|
54824
|
+
}
|
|
54825
|
+
const withCumulative = [];
|
|
54826
|
+
for (const order of sortedOrders) {
|
|
54827
|
+
withCumulative.push({
|
|
54828
|
+
...order,
|
|
54829
|
+
cumulative_quantity: runningTotal
|
|
54830
|
+
});
|
|
54831
|
+
runningTotal -= order.quantity;
|
|
54832
|
+
runningTotal = to_f2(runningTotal, decimal_places);
|
|
54833
|
+
}
|
|
54834
|
+
const positions = await this.getPositionInfo(symbol);
|
|
54835
|
+
const position2 = positions[kind] || {
|
|
54836
|
+
kind,
|
|
54837
|
+
size: 0,
|
|
54838
|
+
entryPrice: 0,
|
|
54839
|
+
symbol
|
|
54840
|
+
};
|
|
54841
|
+
const filteredOrders = withCumulative.filter((order) => (order.cumulative_quantity || 0) > position2.size).map((order) => ({
|
|
54842
|
+
...order,
|
|
54843
|
+
price: order.entry,
|
|
54844
|
+
kind,
|
|
54845
|
+
side: kind.toLowerCase() === "long" ? "buy" : "sell"
|
|
54846
|
+
}));
|
|
54847
|
+
if (filteredOrders.length > 0 && place) {
|
|
54848
|
+
await this.cancelAllOrders(symbol, {
|
|
54849
|
+
type: "limit",
|
|
54850
|
+
kind
|
|
54851
|
+
});
|
|
54852
|
+
await this._createLimitPurchaseOrders({
|
|
54853
|
+
symbol,
|
|
54854
|
+
orders: filteredOrders,
|
|
54855
|
+
price_places,
|
|
54856
|
+
decimal_places
|
|
54857
|
+
});
|
|
54858
|
+
}
|
|
54859
|
+
return filteredOrders;
|
|
54860
|
+
}
|
|
54861
|
+
async get_current_price(symbol) {
|
|
54862
|
+
return await this.getCurrentPrice(symbol);
|
|
54863
|
+
}
|
|
54864
|
+
async getExchangeAccountInfo(options) {
|
|
54865
|
+
const {
|
|
54866
|
+
price_places = "%.1f",
|
|
54867
|
+
decimal_places = "%.3f",
|
|
54868
|
+
account,
|
|
54869
|
+
symbol
|
|
54870
|
+
} = options;
|
|
54871
|
+
return await this.getExchangeInfo({
|
|
54872
|
+
price_places,
|
|
54873
|
+
decimal_places,
|
|
54874
|
+
account,
|
|
54875
|
+
symbol
|
|
54876
|
+
});
|
|
54877
|
+
}
|
|
54878
|
+
async cancelOrders(payload) {
|
|
54879
|
+
return await this._cancelOrders({
|
|
54880
|
+
symbol: payload.symbol,
|
|
54881
|
+
orders: payload.orders.map((x) => ({ orderId: x }))
|
|
54882
|
+
});
|
|
54883
|
+
}
|
|
54884
|
+
async placeTpOrder(payload) {
|
|
54885
|
+
return await this._placeTpOrder({
|
|
54886
|
+
symbol: payload.symbol,
|
|
54887
|
+
tp: payload.take_profit,
|
|
54888
|
+
kind: payload.kind,
|
|
54889
|
+
quantity: payload.quantity,
|
|
54890
|
+
cancel: true,
|
|
54891
|
+
price_places: payload.price_places,
|
|
54892
|
+
decimal_places: payload.decimal_places
|
|
54893
|
+
});
|
|
54894
|
+
}
|
|
54895
|
+
async placeLimitOrder(payload) {
|
|
54896
|
+
return await this.placeLimitOrders({
|
|
54897
|
+
symbol: payload.symbol,
|
|
54898
|
+
orders: [
|
|
54899
|
+
{
|
|
54900
|
+
entry: payload.price,
|
|
54901
|
+
quantity: payload.quantity
|
|
54902
|
+
}
|
|
54903
|
+
],
|
|
54904
|
+
kind: payload.kind,
|
|
54905
|
+
price_places: payload.price_places,
|
|
54906
|
+
decimal_places: payload.decimal_places
|
|
54907
|
+
});
|
|
54908
|
+
}
|
|
54909
|
+
async placeStopOrder(payload) {
|
|
54910
|
+
const current_price = await this.getCurrentPrice(payload.symbol);
|
|
54911
|
+
return await this._placeStopOrder({
|
|
54912
|
+
symbol: payload.symbol,
|
|
54913
|
+
stop: payload.stop,
|
|
54914
|
+
final_stop: payload.stop,
|
|
54915
|
+
quantity: Math.abs(payload.quantity),
|
|
54916
|
+
kind: payload.kind,
|
|
54917
|
+
cancel: true,
|
|
54918
|
+
is_limit: true,
|
|
54919
|
+
price_places: payload.price_places,
|
|
54920
|
+
decimal_places: payload.decimal_places,
|
|
54921
|
+
current_price
|
|
54922
|
+
});
|
|
54923
|
+
}
|
|
54924
|
+
async closePosition(payload) {
|
|
54925
|
+
const { symbol, kind, price_places, decimal_places } = payload;
|
|
54926
|
+
const currentPrice = await this.getCurrentPrice(symbol);
|
|
54927
|
+
return this.placeTpOrder({
|
|
54928
|
+
price_places,
|
|
54929
|
+
decimal_places,
|
|
54930
|
+
symbol,
|
|
54931
|
+
take_profit: currentPrice,
|
|
54932
|
+
kind
|
|
54933
|
+
});
|
|
54934
|
+
}
|
|
54935
|
+
async getAllOpenSymbols() {
|
|
54936
|
+
const response = await this.getAllOpenOrders();
|
|
54937
|
+
return Array.from(new Set(response.map((x) => x.symbol)));
|
|
54938
|
+
}
|
|
54939
|
+
async createLimitPurchaseOrders(payload) {
|
|
54940
|
+
const {
|
|
54941
|
+
orders,
|
|
54942
|
+
kind,
|
|
54943
|
+
decimal_places = "%.3f",
|
|
54944
|
+
price_places = "%.1f",
|
|
54945
|
+
symbol
|
|
54946
|
+
} = payload;
|
|
54947
|
+
return await this._createLimitPurchaseOrders({
|
|
54948
|
+
symbol,
|
|
54949
|
+
price_places,
|
|
54950
|
+
decimal_places,
|
|
54951
|
+
orders: orders.map((order) => ({
|
|
54952
|
+
...order,
|
|
54953
|
+
price: order.entry,
|
|
54954
|
+
kind,
|
|
54955
|
+
side: kind.toLowerCase() === "long" ? "buy" : "sell"
|
|
54956
|
+
}))
|
|
54957
|
+
});
|
|
54958
|
+
}
|
|
54959
|
+
async placeMarketOrder(payload) {
|
|
54960
|
+
const { symbol, kind, quantity, price_places, decimal_places } = payload;
|
|
54961
|
+
const currentPrice = await this.get_current_price(symbol);
|
|
54962
|
+
return this._createLimitPurchaseOrders({
|
|
54963
|
+
symbol,
|
|
54964
|
+
price_places,
|
|
54965
|
+
decimal_places,
|
|
54966
|
+
orders: [
|
|
54967
|
+
{
|
|
54968
|
+
force_market: true,
|
|
54969
|
+
side: kind === "long" ? "buy" : "sell",
|
|
54970
|
+
kind,
|
|
54971
|
+
quantity,
|
|
54972
|
+
price: currentPrice
|
|
54973
|
+
}
|
|
54974
|
+
]
|
|
54975
|
+
});
|
|
54976
|
+
}
|
|
54783
54977
|
async customStopLoss(payload) {
|
|
54784
54978
|
const {
|
|
54785
54979
|
symbol,
|
|
@@ -54818,6 +55012,33 @@ class BaseExchange {
|
|
|
54818
55012
|
decimal_places
|
|
54819
55013
|
});
|
|
54820
55014
|
}
|
|
55015
|
+
async placeBadStopEntry(payload) {
|
|
55016
|
+
const { symbol, orders, price_places, decimal_places } = payload;
|
|
55017
|
+
const openOrders = await this.getOpenOrders({ symbol });
|
|
55018
|
+
const existingBadEntry = openOrders.filter((k) => {
|
|
55019
|
+
if (k.stopPrice > 0) {
|
|
55020
|
+
if (k.kind === "long" && k.price > k.stopPrice || k.kind === "short" && k.price < k.stopPrice) {
|
|
55021
|
+
return true;
|
|
55022
|
+
}
|
|
55023
|
+
return false;
|
|
55024
|
+
}
|
|
55025
|
+
return false;
|
|
55026
|
+
});
|
|
55027
|
+
if (existingBadEntry.length > 0) {
|
|
55028
|
+
console.log("Cancelling existing bad entry");
|
|
55029
|
+
await this._cancelOrders({
|
|
55030
|
+
symbol,
|
|
55031
|
+
orders: existingBadEntry.map((x) => ({ orderId: x.orderId }))
|
|
55032
|
+
});
|
|
55033
|
+
}
|
|
55034
|
+
console.log("Placing new order");
|
|
55035
|
+
return this._createLimitPurchaseOrders({
|
|
55036
|
+
symbol,
|
|
55037
|
+
price_places,
|
|
55038
|
+
decimal_places,
|
|
55039
|
+
orders
|
|
55040
|
+
});
|
|
55041
|
+
}
|
|
54821
55042
|
async analyzeCandlesticks(payload) {
|
|
54822
55043
|
const { symbol } = payload;
|
|
54823
55044
|
const arr = [
|
|
@@ -54868,6 +55089,10 @@ class BaseExchange {
|
|
|
54868
55089
|
minimum_weekly: minimumWeekly
|
|
54869
55090
|
};
|
|
54870
55091
|
}
|
|
55092
|
+
setAccountDetails(payload) {
|
|
55093
|
+
this.getCredentials = payload.getCredentials;
|
|
55094
|
+
this.proxyAgent = payload.proxyAgent;
|
|
55095
|
+
}
|
|
54871
55096
|
}
|
|
54872
55097
|
|
|
54873
55098
|
// src/exchanges/binance.ts
|
|
@@ -55653,98 +55878,22 @@ async function getAllOpenOrders(payload) {
|
|
|
55653
55878
|
class BinanceExchange extends BaseExchange {
|
|
55654
55879
|
client;
|
|
55655
55880
|
main_client;
|
|
55656
|
-
getCredentials;
|
|
55657
|
-
proxyAgent;
|
|
55658
55881
|
constructor(client, main_client) {
|
|
55659
55882
|
super(client);
|
|
55660
55883
|
this.client = client;
|
|
55661
55884
|
this.main_client = main_client;
|
|
55662
55885
|
}
|
|
55663
|
-
|
|
55664
|
-
this.
|
|
55665
|
-
this.proxyAgent = payload.proxyAgent;
|
|
55886
|
+
async getPositionInfo(symbol) {
|
|
55887
|
+
return await getPositionInfo(this.client, symbol);
|
|
55666
55888
|
}
|
|
55667
|
-
async
|
|
55668
|
-
|
|
55669
|
-
const current_price = await this.get_current_price(payload.symbol);
|
|
55670
|
-
return placeStopOrder(this.client, {
|
|
55671
|
-
symbol: payload.symbol,
|
|
55672
|
-
stop: payload.stop,
|
|
55673
|
-
final_stop: payload.stop,
|
|
55674
|
-
quantity: Math.abs(payload.quantity),
|
|
55675
|
-
kind: payload.kind,
|
|
55676
|
-
cancel: true,
|
|
55677
|
-
is_limit: true,
|
|
55678
|
-
price_places: payload.price_places,
|
|
55679
|
-
decimal_places: payload.decimal_places,
|
|
55680
|
-
current_price
|
|
55681
|
-
});
|
|
55682
|
-
}
|
|
55889
|
+
async getCurrentPrice(symbol) {
|
|
55890
|
+
return await getCurrentPrice(this.client, symbol);
|
|
55683
55891
|
}
|
|
55684
|
-
async
|
|
55685
|
-
|
|
55686
|
-
orders,
|
|
55687
|
-
kind,
|
|
55688
|
-
decimal_places = "%.3f",
|
|
55689
|
-
price_places = "%.1f",
|
|
55690
|
-
symbol
|
|
55691
|
-
} = payload;
|
|
55692
|
-
const _orders = orders.map((order) => ({
|
|
55693
|
-
...order,
|
|
55694
|
-
price: order.entry,
|
|
55695
|
-
kind,
|
|
55696
|
-
side: kind.toLowerCase() === "long" ? "buy" : "sell"
|
|
55697
|
-
}));
|
|
55698
|
-
return await createLimitPurchaseOrders(this.client, symbol, price_places, decimal_places, _orders);
|
|
55892
|
+
async cancelAllOrders(symbol, payload) {
|
|
55893
|
+
return await cancelAllOrders(this.client, symbol, payload);
|
|
55699
55894
|
}
|
|
55700
|
-
async
|
|
55701
|
-
|
|
55702
|
-
orders,
|
|
55703
|
-
kind,
|
|
55704
|
-
decimal_places = "%.3f",
|
|
55705
|
-
price_places = "%.1f",
|
|
55706
|
-
symbol,
|
|
55707
|
-
place = false
|
|
55708
|
-
} = payload;
|
|
55709
|
-
const totalQuantity = orders.reduce((sum, order) => sum + (order.quantity || 0), 0);
|
|
55710
|
-
let runningTotal = to_f2(totalQuantity, decimal_places);
|
|
55711
|
-
let sortedOrders = [...orders].sort((a, b) => (a.entry || 0) - (b.entry || 0));
|
|
55712
|
-
if (kind === "short") {
|
|
55713
|
-
sortedOrders.reverse();
|
|
55714
|
-
}
|
|
55715
|
-
const withCumulative = [];
|
|
55716
|
-
for (const order of sortedOrders) {
|
|
55717
|
-
withCumulative.push({
|
|
55718
|
-
...order,
|
|
55719
|
-
cumulative_quantity: runningTotal
|
|
55720
|
-
});
|
|
55721
|
-
runningTotal -= order.quantity;
|
|
55722
|
-
runningTotal = to_f2(runningTotal, decimal_places);
|
|
55723
|
-
}
|
|
55724
|
-
const positions = await getPositionInfo(this.client, symbol);
|
|
55725
|
-
const position2 = positions[kind] || {
|
|
55726
|
-
kind,
|
|
55727
|
-
size: 0,
|
|
55728
|
-
entryPrice: 0,
|
|
55729
|
-
symbol
|
|
55730
|
-
};
|
|
55731
|
-
const filteredOrders = withCumulative.filter((order) => (order.cumulative_quantity || 0) > position2.size).map((order) => ({
|
|
55732
|
-
...order,
|
|
55733
|
-
price: order.entry,
|
|
55734
|
-
kind,
|
|
55735
|
-
side: kind.toLowerCase() === "long" ? "buy" : "sell"
|
|
55736
|
-
}));
|
|
55737
|
-
if (filteredOrders.length > 0 && place) {
|
|
55738
|
-
await cancelAllOrders(this.client, symbol, {
|
|
55739
|
-
type: "limit",
|
|
55740
|
-
kind
|
|
55741
|
-
});
|
|
55742
|
-
await createLimitPurchaseOrders(this.client, symbol, price_places, decimal_places, filteredOrders);
|
|
55743
|
-
}
|
|
55744
|
-
return filteredOrders;
|
|
55745
|
-
}
|
|
55746
|
-
async get_current_price(symbol) {
|
|
55747
|
-
return await getCurrentPrice(this.client, symbol);
|
|
55895
|
+
async _createLimitPurchaseOrders(payload) {
|
|
55896
|
+
return await createLimitPurchaseOrders(this.client, payload.symbol, payload.price_places, payload.decimal_places, payload.orders);
|
|
55748
55897
|
}
|
|
55749
55898
|
async analyzeCharts(payload) {
|
|
55750
55899
|
return await analyzeCharts({
|
|
@@ -55755,67 +55904,30 @@ class BinanceExchange extends BaseExchange {
|
|
|
55755
55904
|
raw: payload.raw
|
|
55756
55905
|
});
|
|
55757
55906
|
}
|
|
55758
|
-
async
|
|
55759
|
-
const {
|
|
55760
|
-
price_places = "%.1f",
|
|
55761
|
-
decimal_places = "%.3f",
|
|
55762
|
-
account,
|
|
55763
|
-
symbol
|
|
55764
|
-
} = options;
|
|
55907
|
+
async getExchangeInfo(options) {
|
|
55765
55908
|
return await fetchBinanceAccount(this.client, {
|
|
55766
|
-
owner: account.owner,
|
|
55767
|
-
symbol
|
|
55909
|
+
owner: options.account.owner,
|
|
55910
|
+
symbol: options.symbol
|
|
55768
55911
|
}, {
|
|
55769
|
-
price_places,
|
|
55770
|
-
decimal_places
|
|
55912
|
+
price_places: options.price_places,
|
|
55913
|
+
decimal_places: options.decimal_places
|
|
55771
55914
|
});
|
|
55772
55915
|
}
|
|
55773
|
-
async
|
|
55916
|
+
async _cancelOrders(payload) {
|
|
55774
55917
|
return await cancelOrders({
|
|
55775
55918
|
symbol: payload.symbol,
|
|
55776
|
-
orders: payload.orders
|
|
55919
|
+
orders: payload.orders,
|
|
55777
55920
|
custom_client: this.client
|
|
55778
55921
|
});
|
|
55779
55922
|
}
|
|
55780
|
-
async
|
|
55781
|
-
return await placeTpOrder(this.client,
|
|
55782
|
-
symbol: payload.symbol,
|
|
55783
|
-
tp: payload.take_profit,
|
|
55784
|
-
kind: payload.kind,
|
|
55785
|
-
quantity: payload.quantity,
|
|
55786
|
-
cancel: true,
|
|
55787
|
-
price_places: payload.price_places,
|
|
55788
|
-
decimal_places: payload.decimal_places
|
|
55789
|
-
});
|
|
55923
|
+
async _placeTpOrder(payload) {
|
|
55924
|
+
return await placeTpOrder(this.client, payload);
|
|
55790
55925
|
}
|
|
55791
|
-
async
|
|
55792
|
-
return await placeLimitOrders(this.client,
|
|
55793
|
-
symbol: payload.symbol,
|
|
55794
|
-
orders: [
|
|
55795
|
-
{
|
|
55796
|
-
entry: payload.price,
|
|
55797
|
-
quantity: payload.quantity
|
|
55798
|
-
}
|
|
55799
|
-
],
|
|
55800
|
-
kind: payload.kind,
|
|
55801
|
-
price_places: payload.price_places,
|
|
55802
|
-
decimal_places: payload.decimal_places
|
|
55803
|
-
});
|
|
55926
|
+
async placeLimitOrders(payload) {
|
|
55927
|
+
return await placeLimitOrders(this.client, payload);
|
|
55804
55928
|
}
|
|
55805
|
-
async
|
|
55806
|
-
|
|
55807
|
-
return await placeStopOrder(this.client, {
|
|
55808
|
-
symbol: payload.symbol,
|
|
55809
|
-
stop: payload.stop,
|
|
55810
|
-
final_stop: payload.stop,
|
|
55811
|
-
quantity: Math.abs(payload.quantity),
|
|
55812
|
-
kind: payload.kind,
|
|
55813
|
-
cancel: true,
|
|
55814
|
-
is_limit: true,
|
|
55815
|
-
price_places: payload.price_places,
|
|
55816
|
-
decimal_places: payload.decimal_places,
|
|
55817
|
-
current_price
|
|
55818
|
-
});
|
|
55929
|
+
async _placeStopOrder(payload) {
|
|
55930
|
+
return await placeStopOrder(this.client, payload);
|
|
55819
55931
|
}
|
|
55820
55932
|
async setLeverage(payload) {
|
|
55821
55933
|
let maxLeverage = payload.leverage;
|
|
@@ -55909,20 +56021,8 @@ class BinanceExchange extends BaseExchange {
|
|
|
55909
56021
|
const _movers = activeMovers.filter((m) => !toBeDelisted.includes(m.symbol));
|
|
55910
56022
|
return { movers: _movers, delisted };
|
|
55911
56023
|
}
|
|
55912
|
-
async
|
|
55913
|
-
|
|
55914
|
-
const currentPrice = await this.get_current_price(symbol);
|
|
55915
|
-
return this.placeTpOrder({
|
|
55916
|
-
price_places,
|
|
55917
|
-
decimal_places,
|
|
55918
|
-
symbol,
|
|
55919
|
-
take_profit: currentPrice,
|
|
55920
|
-
kind
|
|
55921
|
-
});
|
|
55922
|
-
}
|
|
55923
|
-
async getAllOpenSymbols() {
|
|
55924
|
-
const response = await getAllOpenOrders({ client: this.client });
|
|
55925
|
-
return Array.from(new Set(response.map((x) => x.symbol)));
|
|
56024
|
+
async getAllOpenOrders() {
|
|
56025
|
+
return await getAllOpenOrders({ client: this.client });
|
|
55926
56026
|
}
|
|
55927
56027
|
async getDelistedSpotSymbols() {
|
|
55928
56028
|
if (this.main_client) {
|
|
@@ -55955,49 +56055,9 @@ class BinanceExchange extends BaseExchange {
|
|
|
55955
56055
|
return result;
|
|
55956
56056
|
}
|
|
55957
56057
|
}
|
|
55958
|
-
async placeMarketOrder(payload) {
|
|
55959
|
-
const { symbol, kind, quantity, price_places, decimal_places } = payload;
|
|
55960
|
-
const currentPrice = await this.get_current_price(symbol);
|
|
55961
|
-
return createLimitPurchaseOrders(this.client, symbol, price_places, decimal_places, [
|
|
55962
|
-
{
|
|
55963
|
-
force_market: true,
|
|
55964
|
-
side: kind === "long" ? "buy" : "sell",
|
|
55965
|
-
kind,
|
|
55966
|
-
quantity,
|
|
55967
|
-
price: currentPrice
|
|
55968
|
-
}
|
|
55969
|
-
]);
|
|
55970
|
-
}
|
|
55971
|
-
async rawCreateLimitPurchaseOrders(payload) {
|
|
55972
|
-
const { symbol, orders, price_places, decimal_places } = payload;
|
|
55973
|
-
return createLimitPurchaseOrders(this.client, symbol, price_places, decimal_places, orders);
|
|
55974
|
-
}
|
|
55975
56058
|
async getOpenOrders(payload) {
|
|
55976
56059
|
return await getOpenOrders(this.client, payload.symbol);
|
|
55977
56060
|
}
|
|
55978
|
-
async placeBadStopEntry(payload) {
|
|
55979
|
-
const { symbol, orders, price_places, decimal_places } = payload;
|
|
55980
|
-
const openOrders = await this.getOpenOrders({ symbol });
|
|
55981
|
-
const existingBadEntry = openOrders.filter((k) => {
|
|
55982
|
-
if (k.stopPrice > 0) {
|
|
55983
|
-
if (k.kind === "long" && k.price > k.stopPrice || k.kind === "short" && k.price < k.stopPrice) {
|
|
55984
|
-
return true;
|
|
55985
|
-
}
|
|
55986
|
-
return false;
|
|
55987
|
-
}
|
|
55988
|
-
return false;
|
|
55989
|
-
});
|
|
55990
|
-
if (existingBadEntry.length > 0) {
|
|
55991
|
-
console.log("Cancelling existing bad entry");
|
|
55992
|
-
await cancelOrders({
|
|
55993
|
-
symbol,
|
|
55994
|
-
orders: existingBadEntry.map((x) => ({ orderId: x.orderId })),
|
|
55995
|
-
custom_client: this.client
|
|
55996
|
-
});
|
|
55997
|
-
}
|
|
55998
|
-
console.log("Placing new order");
|
|
55999
|
-
return createLimitPurchaseOrders(this.client, symbol, price_places, decimal_places, orders);
|
|
56000
|
-
}
|
|
56001
56061
|
}
|
|
56002
56062
|
function getPricePlaces(target) {
|
|
56003
56063
|
const numStr = target.toString();
|
|
@@ -56195,10 +56255,11 @@ async function placeStopOrder2(client, payload) {
|
|
|
56195
56255
|
kind: payload.kind
|
|
56196
56256
|
});
|
|
56197
56257
|
}
|
|
56258
|
+
const spread = 1.00005;
|
|
56198
56259
|
const order = {
|
|
56199
56260
|
kind: payload.kind,
|
|
56200
56261
|
side: payload.kind === "long" ? "sell" : "buy",
|
|
56201
|
-
price: payload.stop,
|
|
56262
|
+
price: payload.kind === "long" ? payload.stop * spread ** -1 : payload.stop * spread,
|
|
56202
56263
|
quantity: payload.quantity,
|
|
56203
56264
|
stop: payload.final_stop,
|
|
56204
56265
|
is_market: !payload.is_limit
|
|
@@ -56494,6 +56555,28 @@ async function analyzeCharts2(params) {
|
|
|
56494
56555
|
}
|
|
56495
56556
|
return finalPairs;
|
|
56496
56557
|
}
|
|
56558
|
+
async function getAllOpenOrders2(payload) {
|
|
56559
|
+
const { client, currency = "USDT" } = payload;
|
|
56560
|
+
const response = await client.getActiveOrders({
|
|
56561
|
+
category: "linear",
|
|
56562
|
+
openOnly: 0,
|
|
56563
|
+
settleCoin: currency
|
|
56564
|
+
});
|
|
56565
|
+
let cursor = response.result.nextPageCursor;
|
|
56566
|
+
const orders = response.result.list || [];
|
|
56567
|
+
while (Boolean(cursor)) {
|
|
56568
|
+
const nextResponse = await client.getActiveOrders({
|
|
56569
|
+
category: "linear",
|
|
56570
|
+
openOnly: 0,
|
|
56571
|
+
settleCoin: currency,
|
|
56572
|
+
cursor
|
|
56573
|
+
});
|
|
56574
|
+
orders.push(...nextResponse.result.list);
|
|
56575
|
+
cursor = nextResponse.result.nextPageCursor;
|
|
56576
|
+
console.log("getAllOpenOrders cursor", cursor);
|
|
56577
|
+
}
|
|
56578
|
+
return orders;
|
|
56579
|
+
}
|
|
56497
56580
|
|
|
56498
56581
|
class BybitExchange extends BaseExchange {
|
|
56499
56582
|
client;
|
|
@@ -56503,68 +56586,16 @@ class BybitExchange extends BaseExchange {
|
|
|
56503
56586
|
this.client = client;
|
|
56504
56587
|
this.main_client = main_client;
|
|
56505
56588
|
}
|
|
56506
|
-
async
|
|
56507
|
-
|
|
56508
|
-
return placeStopOrder2(this.client, {
|
|
56509
|
-
symbol: payload.symbol,
|
|
56510
|
-
stop: payload.stop,
|
|
56511
|
-
final_stop: payload.stop,
|
|
56512
|
-
quantity: Math.abs(payload.quantity),
|
|
56513
|
-
kind: payload.kind,
|
|
56514
|
-
cancel: true,
|
|
56515
|
-
is_limit: true,
|
|
56516
|
-
price_places: payload.price_places,
|
|
56517
|
-
decimal_places: payload.decimal_places
|
|
56518
|
-
});
|
|
56519
|
-
}
|
|
56589
|
+
async getPositionInfo(symbol) {
|
|
56590
|
+
return await getPositionInfo2(this.client, symbol);
|
|
56520
56591
|
}
|
|
56521
|
-
async
|
|
56522
|
-
|
|
56523
|
-
orders,
|
|
56524
|
-
kind,
|
|
56525
|
-
decimal_places = "%.3f",
|
|
56526
|
-
price_places = "%.1f",
|
|
56527
|
-
symbol,
|
|
56528
|
-
place = false
|
|
56529
|
-
} = payload;
|
|
56530
|
-
const totalQuantity = orders.reduce((sum, order) => sum + (order.quantity || 0), 0);
|
|
56531
|
-
let runningTotal = to_f2(totalQuantity, decimal_places);
|
|
56532
|
-
let sortedOrders = [...orders].sort((a, b) => (a.entry || 0) - (b.entry || 0));
|
|
56533
|
-
if (kind === "short") {
|
|
56534
|
-
sortedOrders.reverse();
|
|
56535
|
-
}
|
|
56536
|
-
const withCumulative = [];
|
|
56537
|
-
for (const order of sortedOrders) {
|
|
56538
|
-
withCumulative.push({
|
|
56539
|
-
...order,
|
|
56540
|
-
cumulative_quantity: runningTotal
|
|
56541
|
-
});
|
|
56542
|
-
runningTotal -= order.quantity;
|
|
56543
|
-
runningTotal = to_f2(runningTotal, decimal_places);
|
|
56544
|
-
}
|
|
56545
|
-
const positions = await getPositionInfo2(this.client, symbol);
|
|
56546
|
-
const position2 = positions[kind] || {
|
|
56547
|
-
kind,
|
|
56548
|
-
size: 0,
|
|
56549
|
-
entryPrice: 0,
|
|
56550
|
-
symbol
|
|
56551
|
-
};
|
|
56552
|
-
const filteredOrders = withCumulative.filter((order) => (order.cumulative_quantity || 0) > position2.size).map((order) => ({
|
|
56553
|
-
...order,
|
|
56554
|
-
price: order.entry,
|
|
56555
|
-
kind,
|
|
56556
|
-
side: kind.toLowerCase() === "long" ? "buy" : "sell"
|
|
56557
|
-
}));
|
|
56558
|
-
if (filteredOrders.length > 0 && place) {
|
|
56559
|
-
await cancelAllOrders2(this.client, symbol, {
|
|
56560
|
-
type: "limit",
|
|
56561
|
-
kind
|
|
56562
|
-
});
|
|
56563
|
-
await createLimitPurchaseOrders2(this.client, symbol, price_places, decimal_places, filteredOrders);
|
|
56564
|
-
}
|
|
56565
|
-
return filteredOrders;
|
|
56592
|
+
async cancelAllOrders(symbol, payload) {
|
|
56593
|
+
return await cancelAllOrders2(this.client, symbol, payload);
|
|
56566
56594
|
}
|
|
56567
|
-
async
|
|
56595
|
+
async _createLimitPurchaseOrders(payload) {
|
|
56596
|
+
return await createLimitPurchaseOrders2(this.client, payload.symbol, payload.price_places, payload.decimal_places, payload.orders);
|
|
56597
|
+
}
|
|
56598
|
+
async getCurrentPrice(symbol) {
|
|
56568
56599
|
return await getCurrentPrice2(this.client, symbol);
|
|
56569
56600
|
}
|
|
56570
56601
|
async analyzeCharts(payload) {
|
|
@@ -56576,60 +56607,30 @@ class BybitExchange extends BaseExchange {
|
|
|
56576
56607
|
raw: payload.raw || false
|
|
56577
56608
|
});
|
|
56578
56609
|
}
|
|
56579
|
-
async
|
|
56580
|
-
const {
|
|
56581
|
-
price_places = "%.1f",
|
|
56582
|
-
decimal_places = "%.3f",
|
|
56583
|
-
account,
|
|
56584
|
-
symbol
|
|
56585
|
-
} = options;
|
|
56610
|
+
async getExchangeInfo(options) {
|
|
56586
56611
|
return await fetchBybitAccount(this.client, {
|
|
56587
|
-
owner: account.owner,
|
|
56588
|
-
symbol
|
|
56612
|
+
owner: options.account.owner,
|
|
56613
|
+
symbol: options.symbol
|
|
56589
56614
|
}, {
|
|
56590
|
-
price_places,
|
|
56591
|
-
decimal_places
|
|
56615
|
+
price_places: options.price_places,
|
|
56616
|
+
decimal_places: options.decimal_places
|
|
56592
56617
|
});
|
|
56593
56618
|
}
|
|
56594
|
-
async
|
|
56619
|
+
async _cancelOrders(payload) {
|
|
56595
56620
|
return await cancelOrders2({
|
|
56596
56621
|
symbol: payload.symbol,
|
|
56597
|
-
orders: payload.orders
|
|
56622
|
+
orders: payload.orders,
|
|
56598
56623
|
custom_client: this.client
|
|
56599
56624
|
});
|
|
56600
56625
|
}
|
|
56601
|
-
async
|
|
56602
|
-
return await placeTpOrder2(this.client,
|
|
56603
|
-
symbol: payload.symbol,
|
|
56604
|
-
tp: payload.take_profit,
|
|
56605
|
-
kind: payload.kind,
|
|
56606
|
-
cancel: true
|
|
56607
|
-
});
|
|
56626
|
+
async _placeTpOrder(payload) {
|
|
56627
|
+
return await placeTpOrder2(this.client, payload);
|
|
56608
56628
|
}
|
|
56609
|
-
async
|
|
56610
|
-
return await placeLimitOrders2(this.client,
|
|
56611
|
-
symbol: payload.symbol,
|
|
56612
|
-
orders: [
|
|
56613
|
-
{
|
|
56614
|
-
entry: payload.price,
|
|
56615
|
-
quantity: payload.quantity
|
|
56616
|
-
}
|
|
56617
|
-
],
|
|
56618
|
-
kind: payload.kind
|
|
56619
|
-
});
|
|
56629
|
+
async placeLimitOrders(payload) {
|
|
56630
|
+
return await placeLimitOrders2(this.client, payload);
|
|
56620
56631
|
}
|
|
56621
|
-
async
|
|
56622
|
-
return await placeStopOrder2(this.client,
|
|
56623
|
-
symbol: payload.symbol,
|
|
56624
|
-
stop: payload.stop,
|
|
56625
|
-
final_stop: payload.stop,
|
|
56626
|
-
quantity: Math.abs(payload.quantity),
|
|
56627
|
-
kind: payload.kind,
|
|
56628
|
-
cancel: true,
|
|
56629
|
-
is_limit: true,
|
|
56630
|
-
price_places: payload.price_places,
|
|
56631
|
-
decimal_places: payload.decimal_places
|
|
56632
|
-
});
|
|
56632
|
+
async _placeStopOrder(payload) {
|
|
56633
|
+
return await placeStopOrder2(this.client, payload);
|
|
56633
56634
|
}
|
|
56634
56635
|
async setLeverage(payload) {
|
|
56635
56636
|
return await this.client.setLeverage({
|
|
@@ -56643,40 +56644,18 @@ class BybitExchange extends BaseExchange {
|
|
|
56643
56644
|
}
|
|
56644
56645
|
async checkDelistedMovers(payload) {
|
|
56645
56646
|
}
|
|
56646
|
-
async
|
|
56647
|
-
|
|
56648
|
-
|
|
56649
|
-
return [];
|
|
56647
|
+
async getAllOpenOrders() {
|
|
56648
|
+
const result = await getAllOpenOrders2({ client: this.client });
|
|
56649
|
+
return result;
|
|
56650
56650
|
}
|
|
56651
56651
|
async getOpenPositions() {
|
|
56652
56652
|
return [];
|
|
56653
56653
|
}
|
|
56654
|
-
async createLimitPurchaseOrders(payload) {
|
|
56655
|
-
const {
|
|
56656
|
-
orders,
|
|
56657
|
-
kind,
|
|
56658
|
-
decimal_places = "%.3f",
|
|
56659
|
-
price_places = "%.1f",
|
|
56660
|
-
symbol
|
|
56661
|
-
} = payload;
|
|
56662
|
-
return await createLimitPurchaseOrders2(this.client, symbol, price_places, decimal_places, orders.map((order) => ({
|
|
56663
|
-
...order,
|
|
56664
|
-
price: order.entry,
|
|
56665
|
-
kind,
|
|
56666
|
-
side: kind.toLowerCase() === "long" ? "buy" : "sell"
|
|
56667
|
-
})));
|
|
56668
|
-
}
|
|
56669
56654
|
async getDelistedSpotSymbols() {
|
|
56670
56655
|
return [];
|
|
56671
56656
|
}
|
|
56672
56657
|
async crossAccountTransfer(payload) {
|
|
56673
56658
|
}
|
|
56674
|
-
async placeMarketOrder(payload) {
|
|
56675
|
-
}
|
|
56676
|
-
async rawCreateLimitPurchaseOrders(payload) {
|
|
56677
|
-
const { symbol, orders, price_places, decimal_places } = payload;
|
|
56678
|
-
return createLimitPurchaseOrders2(this.client, symbol, price_places, decimal_places, orders);
|
|
56679
|
-
}
|
|
56680
56659
|
getOpenOrders(payload) {
|
|
56681
56660
|
return getOpenOrders2(this.client, payload.symbol);
|
|
56682
56661
|
}
|
|
@@ -58112,6 +58091,9 @@ class ExchangeAccount {
|
|
|
58112
58091
|
long_config,
|
|
58113
58092
|
short_config
|
|
58114
58093
|
});
|
|
58094
|
+
if (!long_config || !short_config) {
|
|
58095
|
+
return null;
|
|
58096
|
+
}
|
|
58115
58097
|
let long_target_pnl = payload.kind == "long" ? payload.target_pnl : 0;
|
|
58116
58098
|
let short_target_pnl = payload.kind == "short" ? payload.target_pnl : 0;
|
|
58117
58099
|
const long_sell_ratio = long_config.sell_ratio || long_position?.sell_ratio;
|
|
@@ -58236,7 +58218,7 @@ class ExchangeAccount {
|
|
|
58236
58218
|
});
|
|
58237
58219
|
const long_pause_tp = long_config?.pause_tp;
|
|
58238
58220
|
const short_pause_tp = short_config?.pause_tp;
|
|
58239
|
-
if (payload.trigger && !long_pause_tp && !short_pause_tp) {
|
|
58221
|
+
if (payload.trigger && !long_pause_tp && !short_pause_tp && config2) {
|
|
58240
58222
|
return await this.reduceMajorPositionEntry({
|
|
58241
58223
|
symbol,
|
|
58242
58224
|
long: config2.long,
|
|
@@ -58800,15 +58782,15 @@ class ExchangeAccount {
|
|
|
58800
58782
|
}
|
|
58801
58783
|
async buildOppositeTrades(payload) {
|
|
58802
58784
|
const { symbol, kind, place, place_symbol } = payload;
|
|
58803
|
-
const
|
|
58785
|
+
const strategy2 = await this.runSimulation({
|
|
58804
58786
|
symbol,
|
|
58805
58787
|
kind,
|
|
58806
58788
|
raw: true
|
|
58807
58789
|
});
|
|
58808
58790
|
try {
|
|
58809
|
-
const result =
|
|
58791
|
+
const result = strategy2.generateOppositeTrades({
|
|
58810
58792
|
kind,
|
|
58811
|
-
avg_entry:
|
|
58793
|
+
avg_entry: strategy2.position[kind].avg_price
|
|
58812
58794
|
});
|
|
58813
58795
|
if (place && result?.kind) {
|
|
58814
58796
|
const _symbol = place_symbol || symbol;
|
|
@@ -58859,7 +58841,7 @@ class ExchangeAccount {
|
|
|
58859
58841
|
reduce_ratio,
|
|
58860
58842
|
global_config: symbol_config
|
|
58861
58843
|
};
|
|
58862
|
-
const
|
|
58844
|
+
const strategy2 = new Strategy({
|
|
58863
58845
|
long: {
|
|
58864
58846
|
entry: long_position.entry,
|
|
58865
58847
|
quantity: long_position.quantity,
|
|
@@ -58875,9 +58857,9 @@ class ExchangeAccount {
|
|
|
58875
58857
|
config: strategy_config
|
|
58876
58858
|
});
|
|
58877
58859
|
if (raw) {
|
|
58878
|
-
return
|
|
58860
|
+
return strategy2;
|
|
58879
58861
|
}
|
|
58880
|
-
return
|
|
58862
|
+
return strategy2.runIterations({
|
|
58881
58863
|
iterations,
|
|
58882
58864
|
kind
|
|
58883
58865
|
});
|
|
@@ -59566,31 +59548,31 @@ class ExchangeAccount {
|
|
|
59566
59548
|
if (!focus_position) {
|
|
59567
59549
|
return;
|
|
59568
59550
|
}
|
|
59569
|
-
const
|
|
59570
|
-
if (!
|
|
59551
|
+
const strategy2 = focus_position?.expand?.account_strategy;
|
|
59552
|
+
if (!strategy2) {
|
|
59571
59553
|
return;
|
|
59572
59554
|
}
|
|
59573
|
-
const risk =
|
|
59574
|
-
const kind =
|
|
59575
|
-
const support =
|
|
59576
|
-
const resistance =
|
|
59555
|
+
const risk = strategy2.risk;
|
|
59556
|
+
const kind = strategy2.kind;
|
|
59557
|
+
const support = strategy2.support;
|
|
59558
|
+
const resistance = strategy2.resistance;
|
|
59577
59559
|
console.log("Getting long and short positions for ", symbol);
|
|
59578
59560
|
const long_position = positions.find((k) => k.kind === "long");
|
|
59579
59561
|
const short_position = positions.find((k) => k.kind === "short");
|
|
59580
59562
|
console.log("Getting focus position for ", symbol, kind);
|
|
59581
59563
|
const reverse_position = kind === "long" ? short_position : long_position;
|
|
59582
|
-
if (
|
|
59583
|
-
reward_factor =
|
|
59564
|
+
if (strategy2.max_reward_factor === 0) {
|
|
59565
|
+
reward_factor = strategy2.reward_factor;
|
|
59584
59566
|
}
|
|
59585
|
-
if (focus_position.avg_qty >= focus_position.quantity &&
|
|
59586
|
-
if (
|
|
59567
|
+
if (focus_position.avg_qty >= focus_position.quantity && strategy2.max_reward_factor) {
|
|
59568
|
+
if (strategy2.dynamic) {
|
|
59587
59569
|
const quantity_ratio = focus_position.quantity / focus_position.avg_qty;
|
|
59588
|
-
reward_factor = to_f2(quantity_ratio ** 2 *
|
|
59570
|
+
reward_factor = to_f2(quantity_ratio ** 2 * strategy2.max_reward_factor, "%.2f");
|
|
59589
59571
|
} else {
|
|
59590
|
-
reward_factor = to_f2(focus_position.quantity *
|
|
59572
|
+
reward_factor = to_f2(focus_position.quantity * strategy2.max_reward_factor / focus_position.avg_qty, "%.4f");
|
|
59591
59573
|
}
|
|
59592
59574
|
} else {
|
|
59593
|
-
reward_factor =
|
|
59575
|
+
reward_factor = strategy2.reward_factor;
|
|
59594
59576
|
}
|
|
59595
59577
|
console.log("Getting entry and stop for ", symbol, kind);
|
|
59596
59578
|
const entry = kind === "long" ? resistance : support;
|
|
@@ -59604,7 +59586,7 @@ class ExchangeAccount {
|
|
|
59604
59586
|
symbol
|
|
59605
59587
|
});
|
|
59606
59588
|
console.log("Computing risk reward for ", symbol, kind);
|
|
59607
|
-
const risk_reward =
|
|
59589
|
+
const risk_reward = strategy2.risk_reward || computeRiskReward({
|
|
59608
59590
|
app_config: initial_app_config,
|
|
59609
59591
|
entry: initial_app_config.entry,
|
|
59610
59592
|
stop: initial_app_config.stop,
|
|
@@ -59737,7 +59719,7 @@ class ExchangeAccount {
|
|
|
59737
59719
|
const max_size = app_config.max_size * 0.98;
|
|
59738
59720
|
if (reverse_config.threshold_qty !== max_size) {
|
|
59739
59721
|
await this.app_db.updateScheduledTrade(reverse_config.id, {
|
|
59740
|
-
follow:
|
|
59722
|
+
follow: strategy2.follow,
|
|
59741
59723
|
threshold_qty: max_size
|
|
59742
59724
|
});
|
|
59743
59725
|
}
|
|
@@ -59811,8 +59793,8 @@ class ExchangeAccount {
|
|
|
59811
59793
|
}
|
|
59812
59794
|
const reverse_kind = focus_position.kind === "long" ? "short" : "long";
|
|
59813
59795
|
const reverse_position = positions.find((k) => k.kind === reverse_kind);
|
|
59814
|
-
const
|
|
59815
|
-
if (!
|
|
59796
|
+
const strategy2 = focus_position?.expand?.account_strategy;
|
|
59797
|
+
if (!strategy2) {
|
|
59816
59798
|
return;
|
|
59817
59799
|
}
|
|
59818
59800
|
return computeProfitDetail({
|
|
@@ -59825,9 +59807,9 @@ class ExchangeAccount {
|
|
|
59825
59807
|
},
|
|
59826
59808
|
pnl: focus_position.target_pnl,
|
|
59827
59809
|
strategy: {
|
|
59828
|
-
reward_factor:
|
|
59829
|
-
risk:
|
|
59830
|
-
max_reward_factor:
|
|
59810
|
+
reward_factor: strategy2.reward_factor,
|
|
59811
|
+
risk: strategy2.risk,
|
|
59812
|
+
max_reward_factor: strategy2.max_reward_factor
|
|
59831
59813
|
},
|
|
59832
59814
|
reduce_position: {
|
|
59833
59815
|
kind: reduce_position.kind,
|
|
@@ -60073,6 +60055,9 @@ class App {
|
|
|
60073
60055
|
owner: exchange.owner,
|
|
60074
60056
|
exchange: exchange.exchange
|
|
60075
60057
|
});
|
|
60058
|
+
if (exchange.exchange === "bybit" && symbol === "BTCUSDC") {
|
|
60059
|
+
continue;
|
|
60060
|
+
}
|
|
60076
60061
|
await exchange_account.placeProfitAndStop({
|
|
60077
60062
|
symbol,
|
|
60078
60063
|
trigger: true,
|
|
@@ -60167,11 +60152,11 @@ class App {
|
|
|
60167
60152
|
}
|
|
60168
60153
|
async runDbStrategyAccounts(callback) {
|
|
60169
60154
|
const strategies = await this.app_db.getRunningAccountStrategies();
|
|
60170
|
-
for (const
|
|
60171
|
-
console.log("Running strategy for ",
|
|
60155
|
+
for (const strategy2 of strategies) {
|
|
60156
|
+
console.log("Running strategy for ", strategy2.symbol, "for account", strategy2.expand.account.owner, strategy2.expand.account.exchange);
|
|
60172
60157
|
await callback({
|
|
60173
|
-
symbol:
|
|
60174
|
-
account:
|
|
60158
|
+
symbol: strategy2.symbol,
|
|
60159
|
+
account: strategy2.expand.account
|
|
60175
60160
|
});
|
|
60176
60161
|
}
|
|
60177
60162
|
}
|