forked from fmzquant/strategies
-
Notifications
You must be signed in to change notification settings - Fork 1
/
抢盘口做市策略 - 高频逼近型.js
138 lines (124 loc) · 4.16 KB
/
抢盘口做市策略 - 高频逼近型.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
/*
策略出处: https://www.botvs.com/strategy/348
策略名称: 抢盘口做市策略 - 高频逼近型
策略作者: Zero
策略描述:
抢盘口做市策略, 最基础的做市策略,买一卖一抢单抢盘口, 赚买一卖一的差价.
比如现在卖1是60买1是70, 此策略会以65为中界,65以下布满买单,65以上布满卖单, 因为需要不停的调整订单布局,暂起名为高频逼近型
注意: 模拟测试GetTicker的买一卖一固定差价为1.6, 实际效果需要实盘测试
参数 默认值 描述
------------ ----- ----------
Interval 2000 出错重试间隔(毫秒)
LoopInterval 60 轮询间隔(秒)
Step 0.1 网格间隔(元)
Lot 0.05 手数
MaxNets 20 最大网格数
DisableLog false 关闭订单跟踪
*/
function adjustFloat(v) {
return Math.floor(v*100)/100;
}
function GetOrders() {
var orders = null;
while (!(orders = exchange.GetOrders())) {
Sleep(Interval);
}
return orders;
}
function GetAccount() {
var account;
while (!(account = exchange.GetAccount())) {
Sleep(Interval);
}
return account;
}
function GetTicker(e) {
if (typeof(e) == 'undefined') {
e = exchange;
}
var ticker;
while (!(ticker = e.GetTicker())) {
Sleep(Interval);
}
return ticker;
}
function updateProfit(accountInit, accountNow, ticker) {
var netNow = accountNow.Balance + accountNow.FrozenBalance + ((accountNow.Stocks + accountNow.FrozenStocks) * ticker.Buy);
var netInit = accountInit.Balance + accountInit.FrozenBalance + ((accountInit.Stocks + accountInit.FrozenStocks) * ticker.Buy);
LogProfit(adjustFloat(netNow - netInit));
}
var InitAccount = null;
var LastOrdersLength = null;
function onTick() {
var ticker = GetTicker();
var account = GetAccount();
var orders = GetOrders();
if (LastOrdersLength != null && LastOrdersLength != orders.length) {
updateProfit(InitAccount, account, ticker);
}
LastOrdersLength = orders.length;
var mid = adjustFloat(ticker.Buy + ((ticker.Sell - ticker.Buy) / 2));
var numBuy = parseInt(Math.min(MaxNets / 2 , (mid - ticker.Buy) / Step, account.Balance / ticker.Buy / Lot));
var numSell = parseInt(Math.min(MaxNets / 2, account.Stocks / Lot));
var num = Math.max(numBuy, numSell);
var ordersKeep = [];
var queue = [];
for (var i = 1; i < num; i++) {
var buyPrice = adjustFloat(mid - (i * Step));
var sellPrice = adjustFloat(mid + (i * Step));
var alreadyBuy = false;
var alreadySell = false;
for (j = 0; j < orders.length; j++) {
if (orders[j].Type == ORDER_TYPE_BUY) {
if (Math.abs(orders[j].Price - buyPrice) < (Step / 2)) {
alreadyBuy = true;
ordersKeep.push(orders[j].Id);
}
} else {
if (Math.abs(orders[j].Price - sellPrice) < (Step / 2)) {
alreadySell = true;
ordersKeep.push(orders[j].Id);
}
}
}
if ((!alreadyBuy) && (i < numBuy)) {
queue.push([buyPrice, ORDER_TYPE_BUY]);
}
if ((!alreadySell) && (i < numSell)) {
queue.push([sellPrice, ORDER_TYPE_SELL]);
}
}
for (var i = 0; i < orders.length; i++) {
var keep = false;
for (var j = 0; j < ordersKeep.length; j++) {
if (orders[i].Id == ordersKeep[j]) {
keep = true;
}
}
if (!keep) {
exchange.CancelOrder(orders[i].Id);
LastOrdersLength--;
}
}
for (var i = 0; i < queue.length; i++) {
if (queue[i][1] == ORDER_TYPE_BUY) {
exchange.Buy(queue[i][0], Lot);
} else {
exchange.Sell(queue[i][0], Lot);
}
LastOrdersLength++;
}
}
function main() {
if (DisableLog) {
EnableLog(false);
}
InitAccount = GetAccount();
Log(InitAccount);
LoopInterval = Math.max(LoopInterval, 1);
Lot = Math.max(exchange.GetMinStock(), Lot);
while (true) {
onTick();
Sleep(LoopInterval * 1000);
}
}