forked from fmzquant/strategies
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
root
committed
Feb 7, 2023
1 parent
9e5ffa1
commit a6c574f
Showing
15 changed files
with
1,211 additions
and
239 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
|
||
> 策略名称 | ||
HFT高频订单流因子 | ||
|
||
> 策略作者 | ||
发明者量化 | ||
|
||
> 策略描述 | ||
|
||
一个入门级订单流高频alpha因子, 可以做为市商策略的最优买卖定价距离参考, 信号归一为[-1, 1], 趋向1表示买方市场,趋向-1则是卖方市场, 策略会实时绘制因子值与最后成交价 | ||
策略使用OKX与币安期货websocket接口接收计算, 下图是指标效果, 可以看出有一定的有效性, 公开给高频入门的量化爱好者 | ||
|
||
![IMG](https://www.fmz.com/upload/asset/a89668d3b0189c8902.png) | ||
|
||
|
||
|
||
> 策略参数 | ||
|
||
|
||
|参数|默认值|描述| | ||
|----|----|----| | ||
|QSize|100|QSize| | ||
|
||
|
||
> 源码 (javascript) | ||
``` javascript | ||
let _chart = Chart({ | ||
subtitle: { | ||
text: "Market Status", | ||
}, | ||
yAxis: [{ | ||
height: "60%", | ||
lineWidth: 1, | ||
title: { | ||
text: 'Close', | ||
}, | ||
opposite: true, | ||
labels: { | ||
align: "right", | ||
x: -3, | ||
} | ||
}, { | ||
title: { | ||
text: 'Alpha', | ||
}, | ||
top: "60%", | ||
height: "20%", | ||
offset: 0, | ||
lineWidth: 1 | ||
}, { | ||
title: { | ||
text: 'Vol', | ||
}, | ||
top: "80%", | ||
height: "20%", | ||
offset: 0, | ||
lineWidth: 1 | ||
}], | ||
|
||
series: [{ | ||
name: 'Last', | ||
lineWidth: 1, | ||
data: [], | ||
id: 'primary', | ||
tooltip: { | ||
xDateFormat: '%Y-%m-%d %H:%M:%S' | ||
}, | ||
yAxis: 0 | ||
}, { | ||
type: 'column', | ||
lineWidth: 2, | ||
name: 'Alpha', | ||
data: [], | ||
yAxis: 1, | ||
color: 'green', | ||
zones: [{ | ||
value: 0, | ||
color: 'red' | ||
}] | ||
}, { | ||
lineWidth: 1, | ||
type: 'area', | ||
color: '#257ed4', | ||
name: 'Vol', | ||
data: [], | ||
yAxis: 2 | ||
}], | ||
}) | ||
|
||
function calc_alpha(trades) { | ||
let tick_sell_vol = 0 | ||
let tick_buy_vol = 0 | ||
let last_buy_vol = 0 | ||
let last_sell_vol = 0 | ||
let rightPos = Math.ceil(trades.length * 0.382) | ||
trades.forEach(function(trade, idx) { | ||
if (trade.side == 'buy') { | ||
if (idx >= rightPos) { | ||
last_buy_vol += trade.qty | ||
} | ||
tick_buy_vol += trade.qty | ||
} else { | ||
if (idx >= rightPos) { | ||
last_sell_vol += trade.qty | ||
} | ||
tick_sell_vol += trade.qty | ||
} | ||
}) | ||
|
||
let tanh = function(x) { | ||
// return [-1, 1] | ||
return (Math.exp(x) - Math.exp(-x)) / (Math.exp(x) + Math.exp(-x)) | ||
} | ||
|
||
let positive_ratio = last_buy_vol / tick_sell_vol | ||
let negative_ratio = last_sell_vol / tick_buy_vol | ||
let trade_ratio = 0 | ||
if (positive_ratio > negative_ratio) { | ||
trade_ratio = tanh(positive_ratio) | ||
} else { | ||
trade_ratio = tanh(-negative_ratio) | ||
} | ||
return _N(trade_ratio, 3) | ||
} | ||
|
||
let _trades = [] | ||
let _vol = 0 | ||
|
||
function onTick(ctx, event) { | ||
if (event.trades) { | ||
event.trades.forEach(function(trade) { | ||
_vol += trade.qty | ||
_trades.push(trade) | ||
if (_trades.length > QSize) { | ||
_trades.shift() | ||
} | ||
}) | ||
if (_trades.length >= QSize) { | ||
let val = calc_alpha(_trades) | ||
_chart.add(0, [event.ts, _trades[_trades.length-1].price]) | ||
_chart.add(1, [event.ts, val]) | ||
_chart.add(2, [event.ts, _vol]) | ||
_vol = 0 | ||
} | ||
} | ||
} | ||
|
||
function main() { | ||
let ctName = "swap" | ||
_chart.reset() | ||
let ctx = $.NewWSS(exchange, function(ws, e) { | ||
let msg = null | ||
if (e.GetName() == 'Futures_OKCoin') { | ||
msg = { | ||
op: "subscribe", | ||
args: [] | ||
} | ||
let instId = e.SetContractType(ctName).InstrumentID | ||
msg.args.push({ | ||
channel: "books5", | ||
instId: instId | ||
}) | ||
msg.args.push({ | ||
channel: "trades", | ||
instId: instId | ||
}) | ||
} else { | ||
msg = { | ||
method: "SUBSCRIBE", | ||
params: [], | ||
id: "1" | ||
} | ||
let symbol = e.GetCurrency().replace('_', '').toLowerCase() | ||
msg.params.push(symbol + "@aggTrade") | ||
msg.params.push(symbol + "@depth20@100ms") | ||
} | ||
ws.write(JSON.stringify(msg)) | ||
Log("subscribe", msg, "channel") | ||
LogStatus("Ready") | ||
}, onTick, false) | ||
|
||
while (true) { | ||
ctx.poll() | ||
EventLoop(1000) | ||
} | ||
} | ||
``` | ||
|
||
> 策略出处 | ||
https://www.fmz.com/strategy/392784 | ||
|
||
> 更新时间 | ||
2023-02-01 19:43:36 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.