forked from fmzquant/strategies
-
Notifications
You must be signed in to change notification settings - Fork 1
/
双平台对冲js版本(two platforms hedging-JS) (Copy).js
225 lines (213 loc) · 8.01 KB
/
双平台对冲js版本(two platforms hedging-JS) (Copy).js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/*
策略出处: https://www.botvs.com/strategy/61405
策略名称: 双平台对冲js版本(two platforms hedging-JS) (Copy)
策略作者: ellajella-0378
策略描述:
参数 默认值 描述
------------ ------ --------
MinSpreadA 0.51 A->B差价
MinSpreadB 0.52 B->A差价
MaxAmount 0.3 最大操作量
BalanceTime 10 平衡周期(秒)
LoopInterval 200 轮询周期(ms)
按钮 默认值 描述
---- ----- ----------
A->B 0.51 更改价差(A->B)
B->A 0.52 更改价差(B->A)
*/
function cancelAll(){
var ref = false;
for(var e in exchanges){
while(true){
var n = 0;
var my_orders = _C(exchanges[e].GetOrders);
for(var order1 in my_orders){
ref = true;
e.CancelOrder(my_orders[order1].Id);
n += 1;
}
if(n==0){
break;
}
}
}
return ret
}
function main(){
if(exchanges.length != 2){
throw("Only two exchanges are supported");
}
LogReset();
LogProfitReset();
cancelAll();
var initStocks = 0.0;
var initBalance = 0.0;
var minAmount = 0.1;
var lastTradeTime = 0;
var lastTradeErrExchange = '';
var accountsCache = [];
var hedgeNum = [0, 0];
var names = [];
var baseCurrency = exchange.GetCurrency();
for(var e in exchanges){
if(exchanges[e].GetCurrency() != baseCurrency){
throw("It has to be the same currency to hedge:"+baseCurrency);
}
names.push(exchanges[e].GetName());
var account = _C(exchanges[e].GetAccount);
accountsCache.push(account);
initStocks += account.Stocks;
initBalance += account.Balance;
}
if(baseCurrency == "BTC"){
minAmount = 0.01
} else {
minAmount = 0.1
}
Log("all balance:", _N(initBalance), "all stocks", _N(initStocks))
while(true){
if(accountsCache.length <= 0){
for(var e in exchanges){
var account1 = _C(exchanges[e].GetAccount);
accountsCache.push(account1);
}
}
Sleep(LoopInterval);
cmd = GetCommand();
if(cmd){
Log("CMD", cmd);
var arr = cmd.split(":");
if(arr[0]=="A->B"){
MinSpreadA = parseFloat(arr[1]);
} else if(arr[0]=="B->A"){
MinSpreadB = parseFloat(arr[1]);
}
}
var depthA = exchanges[0].GetDepth();
if (!depthA){
continue;
}
var depthB = exchanges[1].GetDepth();
if (!depthB){
continue;
}
var time = new Date();
if(lastTradeTime > 0 && time.getTime() - lastTradeTime > BalanceTime){
var needUpdate = cancelAll();
if (!needUpdate){
for(var account2 in accountsCache){
if(accountsCache[account2].FrozenBalance >= 0.1 || accountsCache[account2].FrozenStocks >= 0.001){
needUpdate = true;
break;
}
}
}
if (needUpdate){
for(var k in exchanges){
account3 = _C(exchanges[k].GetAccount);
accountsCache.push(account3);
}
}
var nowStocks = 0.0;
var nowBalance = 0.0;
for(var account4 in accountsCache){
nowBalance += accountsCache[account4].Balance;
nowStocks += accountsCache[account4].Stocks;
}
var diff = _N(nowStocks-initStocks, 5);
var isReverse;
if(Math.abs(diff) < minAmount){
LogProfit(_N(nowBalance-initBalance, 3), "all balance", _N(nowBalance), "all stocks", _N(nowStocks), "stock offset:", diff);
lastTradeTime = 0;
} else if(diff > minAmount){
isReverse = depthA.Bids[0].Price < depthB.Bids[0].Price;
} else if(-diff > minAmount){
isReverse = depthA.Asks[0].Price > depthB.Asks[0].Price;
}
if(isReverse != null){
var depths = [depthA, depthB];
var opAmount;
var kk;
if(isReverse){
kk = [1, 0];
} else{
kk = [0, 1];
}
for(var pos in kk){
if(diff > minAmount){
opAmount = Math.min(diff, accountsCache[pos].Stocks, depths[pos].Bids[0].Amount + depths[pos].Bids[1].Amount);
diff = -opAmount;
if(opAmount >= minAmount){
exchanges[pos].Sell(depths[pos].Bids[1].Price, opAmount);
}
} else if(-diff >= minAmount){
opAmount = Math.min(-diff, _N(accountsCache[pos].Balance / depths[pos].Asks[1].Price, 3), depths[pos].Asks[0].Amount + depths[pos].Asks[1].Amount);
diff += opAmount;
if (opAmount >= minAmount){
exchanges[pos].Buy(depths[pos].Asks[1].Price, opAmount);
}
}
}
if (opAmount != undefined){
var time1 = new Date();
lastTradeTime = time1.getTime();
accountsCache = [];
}
}
continue;
}
var diffA = _N(depthA.Bids[0].Price - depthB.Asks[0].Price, 3)
var diffB = _N(depthB.Bids[0].Price - depthA.Asks[0].Price, 3)
LogStatus(JSON.stringify({type: 'table', title: 'status', cols: ['name', 'money', 'frozenmoney', 'stock', 'frozenstock', 'buyone', 'sellone', 'threshold', 'offset', 'num of times'], rows: [[names[0], accountsCache[0].Balance, accountsCache[0].FrozenBalance, accountsCache[0].Stocks, accountsCache[0].FrozenStocks, depthA.Bids[0].Price, depthA.Asks[0].Price, MinSpreadA, diffA, hedgeNum[0]], [names[1], accountsCache[1].Balance, accountsCache[1].FrozenBalance, accountsCache[1].Stocks, accountsCache[1].FrozenStocks, depthB.Bids[0].Price, depthB.Asks[0].Price, MinSpreadB, diffB, hedgeNum[0]]]}));
HPos = 0;
if (diffA >= MinSpreadA){
orderH = depthA.Bids[0];
orderL = depthB.Asks[0];
exchangeH = 0;
exchangeL = 1;
accountH = accountsCache[0];
accountL = accountsCache[1];
}
else if (diffB >= MinSpreadB){
HPos = 1;
orderH = depthB.Bids[0];
orderL = depthA.Asks[0];
exchangeH = 1;
exchangeL = 0;
accountH = accountsCache[1];
accountL = accountsCache[0];
}
else{
continue;
}
var opPrice = _N((orderH.Price + orderL.Price) / 2.0, 2);
var opAmount = Math.min(MaxAmount, orderH.Amount, orderL.Amount, accountH.Stocks, _N(accountL.Balance / opPrice, 3));
if(opAmount >= minAmount){
var tasks = [[exchangeH, "H"], [exchangeL, "L"]];
if(lastTradeErrExchange == "L"){
tasks.reverse();
}
lastTradeErrExchange = "";
for(var task in tasks){
if(tasks[task][1] == "H"){
var id = exchanges[tasks[task][0]].Sell(opPrice, opAmount);
if(id == undefined){
lastTradeErrExchange = tasks[task][1];
break;
}
}
if(tasks[task][1] == "L"){
var id = exchanges[tasks[task][0]].Buy(opPrice, opAmount);
if(id == undefined){
lastTradeErrExchange = tasks[task][1];
break;
}
}
}
var time = new Date();
lastTradeTime = time.getTime();
accountsCache = []
hedgeNum[HPos] += 1
}
}
}