forked from fmzquant/strategies
-
Notifications
You must be signed in to change notification settings - Fork 0
/
KingKeltner趋势策略_低频.js
139 lines (120 loc) · 4.02 KB
/
KingKeltner趋势策略_低频.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
/*
策略出处: https://www.botvs.com/strategy/42283
策略名称: KingKeltner趋势策略_低频
策略作者: ipqhjjybj
策略描述:
*/
/*
策略出处: vnpy
策略名称: KingKeltner趋势策略
策略作者: ipqhjjybj
策略描述:
趋势跟踪策略
*/
KK_Length = 11 // 计算通道中值的窗口数
kkDev = 1.3 // 计算通道宽度的偏差
trailingPrcnt = 15 // 移动止损
LoopInterval = 60 // 轮询间隔(秒)
SlidePrice = 0.3 // 滑动价(元)
function adjustFloat(v) {
return Math.floor(v*1000)/1000;
}
function CancelPendingOrders() {
while (true) {
var orders = null;
while (!(orders = exchange.GetOrders())) {
Sleep(Interval);
}
if (orders.length == 0) {
return;
}
for (var j = 0; j < orders.length; j++) {
exchange.CancelOrder(orders[j].Id, orders[j]);
if (j < (orders.length-1)) {
Sleep(Interval);
}
}
}
}
function GetAccount() {
var account;
while (!(account = exchange.GetAccount())) {
Sleep(Interval);
}
return account;
}
function GetTicker() {
var ticker;
while (!(ticker = exchange.GetTicker())) {
Sleep(Interval);
}
return ticker;
}
var intraTradeHigh = 0; // 移动最高价
var intraTradeLow = 99999999; // 移动最低价
var LastBuyPrice = 0; // 上一次买的价格
var LastSellPrice = 0; // 上一次卖的价格
var minMoney = 100; // 如果资金小于该数值,则不买入
var LastRecord = null; // 初始化上一个记录
function onTick(exchange) {
var ticker = GetTicker();
// Buy or Sell, Cancel pending orders first
CancelPendingOrders();
var account = GetAccount();
if (true) {
var records = exchange.GetRecords();
if (!records || records.length < (KK_Length + 3)) {
return;
}
// Price not change
var newLast = records[records.length-1];
if ((!LastRecord) || (LastRecord.Time == newLast.Time && LastRecord.Close == newLast.Close)) {
LastRecord = newLast;
return;
}
LastRecord = newLast;
//Log(newLast);
var kk_ATR = TA.ATR(records , KK_Length);
var kk_Mid = TA.MA(records, KK_Length);
var kk_Up = kk_Mid[kk_Mid.length-1] + kk_ATR[kk_ATR.length-1] * kkDev;
//var kk_Down= kk_Mid - kk_ATR * kkDev
//Log("LastRecord.Close",LastRecord.Close ,"kk_up",kk_Up,"intraTradeHigh",intraTradeHigh);
if( account.Stocks <= exchange.GetMinStock() ){
if(LastRecord.Close > kk_Up){
Log("start buy");
var price = ticker.Last + SlidePrice;
var amount = adjustFloat(account.Balance / price);
if (account.Balance > minMoney && amount >= exchange.GetMinStock()) {
if (exchange.Buy(price, amount, "做多")) {
intraTradeHigh = LastRecord.High
intraTradeLow = LastRecord.Low
LastBuyPrice = LastHighPrice = price;
}
}
}
}
else if( exchange.GetMinStock() < account.Stocks ){
Log("Close",LastRecord.Close, "intraTradeHigh",intraTradeHigh ,"intraTradeHigh * ( 1 - trailingPrcnt)",intraTradeHigh * ( 1 - trailingPrcnt/100.0))
intraTradeHigh = Math.max(intraTradeHigh , LastRecord.High)
intraTradeLow = LastRecord.Low
if(LastRecord.Close < intraTradeHigh * ( 1 - trailingPrcnt/100.0)){ // 移动止损
Log("start sell");
var price = ticker.Last - SlidePrice;
var sellAmount = account.Stocks;
if (sellAmount > exchange.GetMinStock()) {
exchange.Sell(ticker.Last - SlidePrice, sellAmount, "卖出");
LastSellPrice = LastLowPrice = price;
}
}
}
}
}
function main() {
InitAccount = GetAccount();
Log(exchange.GetName(), exchange.GetCurrency(), InitAccount);
LoopInterval = Math.max(LoopInterval, 1);
while (true) {
onTick(exchange);
Sleep(LoopInterval*1000);
}
}