量化策略开发,高质量社群,交易思路分享等相关内容
『正文』
ˇ
交易中最重要的是什么?
当然是Timing啊~~~
“时机是这个世界上最难得到,又最容易失去的东西”夫难得而易失者,时也;时至而不旋踵者,机也,故圣人常顺时而动,智者必因机而发.原文出自《九州春秋》
被套不是最难受的,难受的是你止损后行情来了,就差一点你就见到黎明的太阳了。这叫什么?Timing啊~~~
A大架狙一分钟没人来,刚切道具人就拉出来把你秒了,这叫什么?Timing啊~~~
桓温枋头撤军,以精兵叠后,谨慎小心了一路,马上就要回到东晋了松懈了,被慕容垂8000精骑兵突袭死伤过半。这叫什么?Timing啊~~~
人生有太多timing时刻,不是你抓别人的,就是别人抓你的。这个市场何尝不是,我也想抓抓市场的timing,不知可否。
言归正传,我们想抓市场的机会需要有具体的方法和既定规则,我们是做量化的所以每一步都要能说明清楚。
几年前接触到订单流觉得很有意思,它是从微观角度来描述这个市场的,使用最小颗粒的数据计算出主动买卖的指标,找到价格的支撑,阻力,哪个K线主动买入多,哪个是主动卖出多,整个市场主动买卖力量是如何分布的等等之类,它最吸引我的地方是可以用数量描述清楚市场的多空力量。这一点儿对于做量化策略非常关键,可以编写一个完整的交易条件,而不是像某些主观理论存在模棱两可的地方。《订单流图表与普通K线的不同》
订单流不会错吗?错,会经常错。不怕它错,有对应的止损止盈,做的是一个盈亏比。
(图表来源:松鼠沙盘)
(图表来源:松鼠沙盘)
图中的红绿横线就是由多个失衡造成的堆积,分为多头堆积和空头堆积。也就是在某一个K线上出现了供需矛盾极大的情况,有一方占有绝对优势,
这是一个交易的信号。当出现信号时,可以尝试把握这种机会。止损设置在信号K线的最低价或者空头的最高价。以小的试错成本等待一个较大盈亏比的机会。也就是说你要抓主力的timing~哈哈
策略逻辑
1.开仓条件:多头堆积次数大于X做多,空头堆积次数大于X做空.互为正反手。
2.固定止损:以开仓价格的百分比计算止损价。
3.跟踪止盈:以吊灯方法跟踪价格计算出场线。
策略逻辑非常简单,没有那么多弯弯绕。这也是我非常喜欢它的地方,不用动脑子。订单流策略不同于传统技术指标策略,它无法预测信号。如果是MACD或者KDJ,你甚至可以预判到是否会交叉,但是订单流不行。它是基于最小颗粒度计算的主动买卖力量,只能等到它出现你才知道。
策略模块
1.通过tick(或逐笔)数据计算of数据
2.基于of数据计算堆积信号或其他指标
3.合成堆积信号为bar数据进行回测
4.基于CTP实时生成OF数据及信号(实盘版)
盘口策略我们分为俩个版本:回测版和实盘版,今天讲的是回测版本,俱乐部里拿到源码后,群友一定会问很多的问题,策略代码实现较为复杂。我们先消化了回测版,然后7月初发布CTP实盘版。
tick生成of数据:
def orderflow_df_new(df_tick,df_min):
df_of=pd.DataFrame({})
t1 = time.time()
startArray = pd.to_datetime(df_min['starttime']).values
voluememin= df_min['volume'].values
highs=df_min['high'].values
lows=df_min['low'].values
opens=df_min['open'].values
closes=df_min['close'].values
endArray = pd.to_datetime(df_min['datetime']).values
tTickArray = pd.to_datetime(df_tick['datetime']).values
bp1TickArray = df_tick['bid_p'].values
ap1TickArray = df_tick['ask_p'].values
lastTickArray = df_tick['lastprice'].values
volumeTickArray = df_tick['volume'].values
symbolarray = df_tick['symbol'].values
indexFinal = 0
for index,tEnd in enumerate(endArray):
start = startArray[index]
bidDict = {}
askDict = {}
bar_vol=voluememin[index]
bar_close=closes[index]
bar_open=opens[index]
bar_low=lows[index]
bar_high=highs[index]
bar_symbol=symbolarray[index]
dt=endArray[index]
for indexTick in range(indexFinal,len(df_tick)):
#.........................
bidDictResult,askDictResult = process(bidDict,askDict)
bidDictResult=dict(sorted(bidDictResult.items(),key=operator.itemgetter(0)))
askDictResult=dict(sorted(askDictResult.items(),key=operator.itemgetter(0)))
prinslist=list(bidDictResult.keys())
asklist=list(askDictResult.values())
bidlist=list(bidDictResult.values())
delta=(sum(askDictResult.values()) - sum(bidDictResult.values()))
df=pd.DataFrame({'price':pd.Series([prinslist]),'Ask':pd.Series([asklist]),'Bid':pd.Series([bidlist])})
df['symbol']=bar_symbol
df['datetime']=dt
df['delta']=str(delta)
df['close']=bar_close
df['open']=bar_open
df['high']=bar_high
df['low']=bar_low
df['volume']=bar_vol
df['ticktime']=tTickArray[indexTick]
df['dj']=GetOrderFlow_dj(df)
print(df)
df_of = pd.concat([df_of, df], ignore_index=True)
print(time.time() - t1)
return df_of
计算好订单流数据后,输出是这样:
price,Ask,Bid这三列就是订单流K线里的核心数据,入下图:
有了这个脚本,你就可以源源不断的生成orderflow数据用于研究。然后我们在计算每个K线的失衡,堆积。我们的交易条件是基于堆积的,因此我们只要算出堆积列就可以实现Bar级别回测了。如下图:
sig列就是这个bar的堆积次数,正数是多头堆积,负数是空头堆积。
计算堆积的代码:
order= {
"Price":price_s[i],
"Ask":{ "Value":Bid_s[i]},
"Bid":{ "Value":Ask_s[i]}
}
if i>=1 and i<len(price_s)-1:
if (order["Ask"]["Value"]>Ask_s[i+1]*int(Config['Value1'])):
order["Ask"]["Color"]=itemAskBG[1]
gxx+=1
gj+=1
if gj>=int(Config['Value2']) and Config['Value4']==True:
duiji['price']=price_s[i]
duiji['time']=dtime
duiji['longshort']=-1
duiji['cout']=gj
duiji['color']='rgba(0,139,0,0.45)'#绿色
if float(duiji['price'])>0:
djcout+=1
else :
gj=0
if (order["Bid"]["Value"]>Bid_s[i-1]*int(Config['Value1'])):
xq+=1
xxx+=1
order["Bid"]["Color"]=itemBidBG[1]
if xq>=int(Config['Value2']) and Config['Value4']==True:
duiji['price']=price_s[i]
duiji['time']=dtime
duiji['longshort']=1
duiji['cout']=xq
duiji['color']='rgba(255,0,0,0.45)' #红色
if float(duiji['price'])>0:
djcout+=-1
else :
xq=0
为什么要用Bar级别去回测订单流策略?
我们之前开发过很多orderflow策略脚本,详情可以查看orderflow系列。都是逐Tick回测,说实话太慢了,6个月的逐tick回测要好几个小时,这么慢的速度很难做研究,如果你的机器内存小,还有中途崩溃的问题。于是我们改变思路,在数据生成时讲信号计算好,我们只要回测含有信号的Bar就可以了。数据生成+回测用时有了质的飞跃,不到2分钟就可以完成这些工作,如下图:
用时78秒生成了orderflow数据+信号。
然后我们在用10秒回测一下:
回测已经调整好了手续费和滑点,具体品种要针对设置,这也是BackTrader麻烦的地方。为了避免偷价,我们用上一个Bar固定的信号判断,用本根bar的开盘价进行交易。这个回测是沪镍1分钟,回测的时间是2023年1月-6月。
条件设置是:堆积大于5次,正反手,固定止损0.005,固定止盈0.01
还有螺纹5M:
条件设置是:堆积大于0次,正反手,固定止损0.005,固定止盈0.01
关于收益率为什么这么少,因为我下单是1手,初始资金设置的是100W。
我回测了不同品种在同周期参数下的情况,数据较多我就不一一发了,我传到俱乐部后台了,可以下载慢慢看。
另外,要着重说一下,我目前回测没有参数寻优,这种策略逻辑非常特别,不能硬套CTA逻辑。需要针对具体的品种设置参数,如下图:
这是镍的1分钟。
这是螺纹1分钟的信号图,为什么信号数量差距这么大?因为每个品种的盘口特征,活跃度有本质的区别。要对症下药,别动不动就一个套参数打天下,一招鲜吃遍天,你以为是青霉素还是板蓝根?
生成订单流的脚本是基于国内商品的,也可以生成股票,BTC,外盘等标的数据,反正脚本是通用的,关于用什么数据没有要求,只要表头修改好就行。
我们盘口策略会在7月实盘测试,其实群里早就有朋友开始手动操作了,只是今天我们把它做成了全自动。订单流的方方面面还有很大的研究空间,我们提供了最素的版本,大家拿到源码后可以自己玩耍,比传统CTA策略更有意思。
OK,如何使用及完整代码我会录制视频讲解,大家拿到源码后可以在群里发问,想必会有很多问题,我在俱乐部群里等大家。
最后问一句:
你知木知咩叫timing啊?
本策略仅作学习交流使用,实盘交易盈亏投资者个人负责。