量化投资实战笔记
1 基本概念
1、一手股票:100支股票
2、收盘比开盘上涨的百分比:(收盘-开盘)/开盘
3、开盘比前日收盘的百分比:(开盘-前日收盘)/前日收盘
4、从dataframe中取每个月的第一天
df.resample(‘M’).first()
5、从dataframe中取每个年的最后一天
df.resample(‘A’).last()
6、什么是均线
对于每一个交易日,都可以计算出前N天的移动平均值,然后把这些移动平均值连接起来,成为一条线,就叫做N日移动平均线。移动平均线常用线有5天、10天、60天、120天和240天的指标。
- 5天和10天的是短期操作的参考指标,称作日均指标
- 30天和60天的是中期均线指标,称作季均线指标
- 120天和240天的是长期均线指标,称作年均线指标
计算5日均线
df[‘close’].rolling(5).mean()
7、金叉日期和死叉日期
分析指标中的两根线,一根为短期内的指标线,另一根是较长时间的指标线
金叉:如果短时间的指标线方向拐头向上,并且穿过了较长的指标线,这种状态称为金叉。
死叉:如果短时间的指标线方向拐头向下,并且穿过了较长的指标线,这种状态称为死叉。
一般情况下,出现金叉后,操作趋向买入,死叉则趋向卖出。当然,金叉和死叉的只是分析指标之一,要和其他很多指标配合使用,才能增加操作的准确性。
计算死叉的日期
s1 = ma5<ma30
s2 = ma5>ma30
death_ex = s1& s2.shift(1)
df.loc[death_ex]
death_date = df.loc[death_ex].index
计算金叉的日期
s1 = ma5<ma30
s2 = ma5>ma30
gold_ex =-(s1& s2.shift(1))
df.loc[gold_ex]
gold_date = df.loc[gold_ex].index
8、根据金叉买入,死叉卖出
s1 = Series(data=1,index = gold_date)
s2 = Series(data=0,index = death_date)
s = s1.append(s2)
s = s.sort_index()
first_money = 100000 # 本金
money = first_money # 手头剩余的钱
hold = 0 # 持有股票数量
for i in range(0,len(s)):
if s[i]==1:
time = a.index[i]
p = df.loc[time]['open']
hand_count = money//(p*100)
hold = hand_count*100
money -=(hold*p)
else:
death_time = s.index[i]
p_death = df.loc[death_time]['open']
money +=(p_death*hold)
hold = 0
# 剩余股票的价值
last_money =hold = df['close'][-1]
9、计算金叉和死叉
def on_bar(self,bar:BarData):
am = self.am
am.update_bar(bar)
if not am.inited:
return
# 计算技术指标
fast_ma = am.sma(self.fast_window,array=True)
fast_ma0 = fast_ma[-1]
fast_ma1 = fast_ma[-2]
slow_ma = am.sma(self.slow_window,array=True)
slow_ma0 = slow_ma[-1]
slow_ma1 = slow_ma[-2]
# 判断均线交叉
# 金叉
cross_over = (self.fast_ma0 >=self.slow_ma0 and self.fast_ma1 <self.slow_ma1)
cross_below = (slef.fast_ma0 >=self.slow_ma0 and self.slow_ma1 > sefl.fast_ma1)
# 发生金叉
if cross_over:
price = bar.close_price + 10
# 当前没有仓位
if not self.pos:
# 买1手
self.buy(price,1)
# 有空头仓位,需要平掉空头仓位,再买入
elif self.pos<0:
self.cover(price,1)
self.buy(price,1)
# 发生死叉
elif cross_below:
price = bar.close_price - 10
# 当前没有仓位
if not self.pos:
# 做空1手
self.short(price,1)
# 有多头仓位,需要卖掉多头仓位,再做空
elif self.pos>0:
self.sell(price,1)
self.short(price,1)
self.put_event()
10、Tick 数据和Bar数据的区别
Tick 是某种金融产品交易时的逐笔数据。为了高频的 tick 数据从中提取有价值的信息,并以合适的形式存储它们。这种数据储存形式叫做 bar。将右图的单元放大得到两种类型的 bar (绿色空心代表价格上升的 bar,红色实心代表价格下降的 bar):
12、委托和成交的区别
委托中包括了撤单的和成交的。
13、VeighNa回测的K线图标中黄色上三角和蓝色下三角的意义
黄色表示买入做多的位置,蓝色表示卖出做空的位置。
14、VeighNa连接测试TCP
用户名:000300
密码:vnpy1234
经纪商代码:9999
交易服务器:180.168.146.187:10101
行情服务器:180.168.146.187:10101
产品代码:simnow_client_test
授权编码:0000000000000000
15、SimNow 是做什么的?
是上期所全资子公司上期技术公司专门为投资者打造的期货、期权模拟交易平台,为上期所投资者教育网认证的期货、期权模拟仿真系统。
SimNow可以仿真各期货交易所的交易、结算规则,目前已支持国内各期货交易所的商品期货、期权业务。
SimNow的优势:
(1)模拟实盘行情,将实盘价格信息引入仿真
(2)提供7 * 24小时仿真服务
(3)提供TradeNow手机APP,支持手机端操作
(4)便捷开户,直接通过网站注册即可开户,无须线下办理
(5)便捷入金,直接通过网站申请入金
(6)可以支持期货公司等举办仿真交易比赛
16、VeighNa开发一个新指标的过程
以阿隆指标为例。创建my_strategy_tool.py,继承创建NewArrayManager类,新增Aroon指标函数,调用talib的AROON函数,最后返回数组和最新值。
class NewArrayManager(ArrayManager):
def __init__(self,size=100):
super().__init__(size)
def aroon(self,n,array=False):
aroon_up,aroon_down = talib.AROON(self.high,self.low,n)
if array:
return aroon_up,aroon_down
return aroon_up[-1],aroon_down[-1]
17、指标条件逻辑
am = self.am
am.update_bar(bar)
if not am.inited:
return
fast_rsi = am.rsi(self.fast_window,array =True)
slow_rsi = am.rsi(self.slow_window,array =True)
fast_rsi_0 = fast_rsi[-1]
fast_rsi_1 = fast_rsi[-2]
slow_rsi_0 = slow_rsi[-1]
slow_rsi_1 = slow_rsi[-2]
if fast_rsi_0 >=70:
print('over bought')
elif fast_rsi_0<=30:
print('over sold')
# RSI 的金叉与死叉
rsi_crss_over = (fast_rsi_1<slow_rsi_1) and (fast_rsi_0 >=slow_rsi_0)
rsi_crss_below = (fast_rsi_1>slow_rsi_1) and (fast_rsi_0 <=slow_rsi_0)
if rsi_crss_over:
print('we buy')
elif rsi_crss_below:
print('we sell')
18、CTA策略的构成
分为信号、过滤和出场三部分。信号是指赌涨还是跌或者不玩。信号主要分为两类,第一类是信号跟踪类。
其中SMA是指算术平均、EMA是指指数平均、AMA是指自适应性平均。
第二类是趋势突破性信号
过滤是指是否应该下注,出场是指手气不顺要跑。
以RSI指标举例,RSI进入超买区,做多,RSI进入超买器做空
出场逻辑,是指什么时候平仓
价格百分比,移动止损
19、CTA策略中数据回放撮合流程
20、限价单的触发、提交、委托推送流程
21、什么叫市价单、限价单和停止单?
市价单:按市场价来执行的订单。优点是交易快和原理简单、缺点是存在Slippage(实际执行价与期待价格间的价差)
限价单:买入时的限价单是指,就是告诉券商,我要以多少钱买入,比这个价格高就不买,比这个价格低可以;卖出时的限价单是指,就是告诉券商,我要以多少钱卖出,比这个价格低就不卖,比这个价格高就卖,这样限制了成交的最差的价格。优点是避免了Slippage的价差,从而保证价格,缺点是单子可能不会被执行或者只执行了一部分。限价单适合波段交易或者长期投资,对时间不敏感的交易类型,在日交易中,会错过很多交易。
停止单:触发的价格
通常说的限价单是用来入场的,而停止单是用来出场的。
22、停止单撮合
停止单撮合规则一
停止单撮合规则二
23、Dual Trust 策略
做空做多设置一个上轨和下轨,这个轨的范围(Range)的设定,计算公式如下,从(bar中的最高价的最高价HH-收盘价的最高价HC)和(bar中的收盘价的最高价HC-最低价的最低价LL)中选择最大的作为轨的上下范围。
优点是:思路简单、参数不多
缺点是:日内策略,不持仓过夜
特点是:需要日线数据产生信号,分钟线数据进行回测
策略实现思路
(1)全撤委托:清空策略状态
(2)缓存K线:判断是否隔日
(3)计算入场价格:开盘价加减
(4)判断当前时间
- 若交易时间段
- 停止单入场
- 若结束时间段
- 超价平仓
24、通道突破策略
(1)Bollinger Band 布林带策略
布林带是一种多功能工具,结合移动平均线和标准差来检测市场波动的变化。布林带指标包含三个组成部分:
- 中轨 = N时间段的简单移动平均线(SMA)
- 上轨 = 中轨 + K × N时间段的标准差
- 下轨 = 中轨 − K × N时间段的标准差
一般情况下,设定N=20和K=2,这两个数值也是在布林带当中使用最多的。在日线图里,N=20其实就是“月均线”(MA20)。依照正态分布规则,约有95%的数值会分布在距离平均值有正负2个标准差的范围内。
交易规则:价格突破上轨(%b大于等于1),买入开仓,价格突破下轨(%b小于等于0),卖出开仓
python 实现
def boll(self,n,dev,array=False):
mid = self.sma(n,array)
std = self.std(n,array)
up = mid+std*dev
down = mid- std*dev
return up,down
(2)肯特纳通道策略(Keltner Channel)
肯特纳通道也是一个基于波动率的技术指标,由三条独立的线组成。Keltner Channels 不使用标准偏差,而是使用平均真实范围 (ATR)来设置通道距离。以下是三个组件:
- 中轨:N时间段的周期指数移动平均线 (EMA)
- 上轨:中轨 +K* 平均真实范围(ATR)
- 下轨:中轨 -K * 平均真实范围(ATR)
python 实现
def keltner(self,n,dev,array=False):
mid = self.sma(n,array)
atr = self.atr(n,array)
up = mid+atr*dev
down = mid- atr*dev
return up,down
(3)唐奇安通道策略
上线=Max(最高价,n),是指n天的最高价
下线=Min(最低价,n),是指n天的最低价
中线=(上线+下线)/2
python实现
def donchian(self,n,array = False):
up = talib.MAX(self.high,n)
down = talib.MIN(self.low,n)
if array:
return up,down
return up[-1],down[-1]
3 参考资料
- 『金融数据结构』「2. 从 Tick 到 Bar」
- VNPY 实战进阶CTA策略网课:https://www.betterbench.top/#/24/detail