量化投资模型策略深度研究(一)

1
回复
5144
查看
[复制链接]

196

主题

140

回帖

1444

积分

管理员

积分
1444
来源: 2019-7-18 06:40:25 显示全部楼层 |阅读模式
   量化投资模型的开发步骤一般是:数据处理、寻找因子、回测验证、实盘模拟、风险归因。

    数据处理:去极值、标准化、中性化;
              
              数据预处理。

    寻找因子:寻找Alpha;

              寻找收益波动比因子

    风险归因:简单策略归因,整理出来,大家有时间可以慢慢研究。

    其实,除模型开发之外,交易系统的构建、回测系统、风控和数据清理等每个部分都很关键。比如数据处理,你用的工具是Matlab还是R,或者c++以及python,如果是工具本身的格式速度会快很多,就像python的npy格式,或者c++的二进制格式。再有就是根据你的不同需求用什么数据,切片数据、分钟数据或者tick数据。每一块都可以是一个坑。

    而量化的模型大致可分为:

    1.趋势形、回复型,都依赖价格数据。

    2.价值型/收益型、成长型和品质型,此类型策略都基于基本面数据。

    3.技术情绪型,较少见,通常都只作为一个辅助因子。

趋势跟随策略

    趋势跟随策略是基于以下的基本假定:市场在一定时间里通常朝着同一方向变化,据此对市场趋势做出判断,就可以作为制定交易策略的依据。定义趋势通常用移动平均线交叉来定义趋势。

MACD移动平均线示例

    MACD(Moving Average Convergence and Divergence)是Geral Appel 于1979年提出的,利用收盘价的短期(常用为12日)指数移动平均线与长期(常用为26日)指数移动平均线之间的聚合与分离状况,对买进、卖出时机作出研判的技术指标。从双移动平均线发展而来的,由快的移动平均线减去慢的移动平均线。MACD的意义和双移动平均线基本相同。但阅读起来更方便。

指标应用法则:

  1.DIF向上交叉MACD,买进;DIF向下交叉MACD,卖出。

  2.DIF连续两次向下交叉MACD,将造成较大的跌幅。

  3.DIF连续两次向上交叉MACD,将造成较大的涨幅。

  4.DIF与股价形成背离时产生的信号,可信度较高。

  5.MDA、MACD、TRIX三者构成一组指标群,互相验证。

  当MACD从负数转向正数,是买的信号。当MACD从正数转向负数,是卖的信号。当MACD以大角度变化,表示快的移动平均线和慢的移动平均线的差距非常迅速的拉开,代表了一个市场大趋势的转变。MACD是Geral Appel 于1979年提出的,它是一项利用短期(常用为12日)移动平均线与长期(常用为26日)移动平均线之间的聚合与分离状况,对买进、卖出时机作出研判的技术指标。

公式算法:
短期EMA: 短期(例如12日)的收盘价指数移动平均值(Exponential Moving Average)
长期EMA: 长期(例如26日)的收盘价指数移动平均值(Exponential Moving Average)
DIF线: (Difference)短期EMA和长期EMA的离差值
DEA线: (Difference Exponential Average)DIF线的M日指数平滑移动平均线
MACD线: DIF线与DEA线的差

参数:
SHORT(短期)、LONG(长期)、M天数,一般为12、26、9。指数加权平滑系数为:
短期EMA平滑系数: 2/(SHORT+1)
长期EMA平滑系数: 2/(LONG+1)
DEA线平滑系数: 2/(M+1)

策略实现:
DIF从下而上穿过DEA,买进;
相反,如DIF从上往下穿过DEA,卖出。

  1. import quartz
  2. import quartz.backtest    as qb
  3. import quartz.performance as qp
  4. from   quartz.api         import *

  5. import pandas as pd
  6. import numpy  as np
  7. from datetime   import datetime
  8. from matplotlib import pylab

  9. import talib



  10. start = datetime(2013, 1, 1)
  11. end = datetime(2015, 1, 22)
  12. benchmark = 'HS300'
  13. #universe = ['601398.XSHG', '600028.XSHG', '601988.XSHG', '600036.XSHG', '600030.XSHG',
  14.             #'601318.XSHG', '600000.XSHG', '600019.XSHG', '600519.XSHG', '601166.XSHG']
  15. universe = set_universe('SH50')
  16. capital_base = 200000
  17. refresh_rate = 1
  18. window = 1

  19. initMACD = -10000.0
  20. histMACD = pd.DataFrame(initMACD, index = universe, columns = ['preShortEMA', 'preLongEMA', 'preDIF', 'preDEA'])
  21. shortWin = 26    # 短期EMA平滑天数
  22. longWin  = 52    # 长期EMA平滑天数
  23. macdWin  = 15    # DEA线平滑天数

  24. def initialize(account):
  25.     account.amount = 10000
  26.     account.universe = universe
  27.     add_history('hist', window)
  28.     account.days = 0
  29.    
  30. def handle_data(account):
  31.     account.days = account.days+1
  32.    
  33.     for stk in account.universe:
  34.         prices = account.hist[stk]['closePrice']
  35.         if prices is None:
  36.             return
  37.         
  38.         preShortEMA = histMACD.at[stk, 'preShortEMA']
  39.         preLongEMA = histMACD.at[stk, 'preLongEMA']
  40.         preDIF = histMACD.at[stk, 'preDIF']
  41.         preDEA = histMACD.at[stk, 'preDEA']
  42.         if preShortEMA == initMACD or preLongEMA == initMACD:
  43.             histMACD.at[stk, 'preShortEMA'] = prices[-1]
  44.             histMACD.at[stk, 'preLongEMA'] = prices[-1]
  45.             histMACD.at[stk, 'preDIF'] = 0
  46.             histMACD.at[stk, 'preDEA'] = 0
  47.             return
  48.             
  49.         shortEMA = preShortEMA*1.0*(shortWin-1)/(shortWin+1) + prices[-1]*2.0/(shortWin+1)
  50.         longEMA = preLongEMA*1.0*(longWin-1)/(longWin+1) + prices[-1]*2.0/(longWin+1)
  51.         DIF = shortEMA - longEMA
  52.         DEA = preDEA*1.0*(macdWin-1)/(macdWin+1) + DIF*2.0/(macdWin+1)
  53.         
  54.         histMACD.at[stk, 'preShortEMA'] = shortEMA
  55.         histMACD.at[stk, 'preLongEMA'] = longEMA
  56.         histMACD.at[stk, 'preDIF'] = DIF
  57.         histMACD.at[stk, 'preDEA'] = DEA
  58.             
  59.         if account.days > longWin and account.days%1 == 0:
  60.             #if DIF > 0 and DEA > 0 and preDIF > preDEA and DIF < DEA:
  61.             if preDIF > preDEA and DIF < DEA:
  62.                 order_to(stk, 0)
  63.             #if DIF < 0 and DEA < 0 and preDIF < preDEA and DIF > DEA:
  64.             if preDIF < preDEA and DIF > DEA:
  65.                 amount = account.amount/prices[-1]
  66.                 order_to(stk, amount)
复制代码





上证指数上的MACD线指标实例:
  1. from CAL.PyCAL import *

  2. # DataAPI.MktIdxdGet返回pandas.DataFrame格式
  3. sh_index =  DataAPI.MktIdxdGet(indexID = "000001.ZICN", beginDate = "20140101", endDate = "20140731")

  4. # calculate DIF, DEA, and MACD
  5. initMACD = -1000.0
  6. sh_index['shortEMA'] = initMACD
  7. sh_index['longEMA']  = initMACD
  8. sh_index['DIF']     = initMACD
  9. sh_index['DEA']  = initMACD
  10. sh_index['MACD']     = initMACD

  11. shortWin = 12
  12. longWin  = 26
  13. macdWin  = 9

  14. index = sh_index.index

  15. for i in range(0, index.shape[0]):
  16.     if i == 0:
  17.         sh_index['shortEMA'].iloc[i] = sh_index['closeIndex'].iloc[i]
  18.         sh_index['longEMA'].iloc[i]  = sh_index['closeIndex'].iloc[i]
  19.         sh_index['DIF'].iloc[i]     = sh_index['shortEMA'].iloc[i] - sh_index['longEMA'].iloc[i]
  20.         sh_index['DEA'].iloc[i]  = sh_index['DIF'].iloc[i]
  21.         sh_index['MACD'].iloc[i]  = sh_index['DIF'].iloc[i] - sh_index['DEA'].iloc[i]
  22.     else:
  23.         sh_index['shortEMA'].iloc[i] = sh_index['closeIndex'].iloc[i]*2.0/(shortWin+1) + sh_index['shortEMA'].iloc[i-1]*(shortWin-1)/(shortWin+1)
  24.         sh_index['longEMA'].iloc[i]  = sh_index['closeIndex'].iloc[i]*2.0/(longWin+1) + sh_index['longEMA'].iloc[i-1]*(longWin-1)/(longWin+1)
  25.         sh_index['DIF'].iloc[i]     = sh_index['shortEMA'].iloc[i] - sh_index['longEMA'].iloc[i]
  26.         sh_index['DEA'].iloc[i]  = sh_index['DIF'].iloc[i]*2.0/(macdWin+1) + sh_index['DIF'].iloc[i-1]*(macdWin-1)/(macdWin+1)
  27.         sh_index['MACD'].iloc[i]  = sh_index['DIF'].iloc[i] - sh_index['DEA'].iloc[i]
  28.         
  29. sh_index = sh_index.set_index('tradeDate')

  30. # plot data
  31. pylab.figure(figsize=(15,6))
  32. pylab.plot(sh_index.index, sh_index.closeIndex)
  33. pylab.plot(sh_index.index, sh_index.longEMA)
  34. pylab.plot(sh_index.index, sh_index.shortEMA)
  35. pylab.legend([u'ShangZheng Index', u'long period EMA', u'short period EMA'], loc = 'best', fontsize = 12)
  36. pylab.grid()

  37. pylab.figure(figsize=(15,6))
  38. pylab.plot(sh_index.index, sh_index.DIF)
  39. pylab.plot(sh_index.index, sh_index.DEA)
  40. pylab.plot(sh_index.index, sh_index.MACD)
  41. pylab.legend([u'DIF line', u'DEA line', u'MACD signal'], loc = 'best', fontsize = 12)
  42. pylab.grid()
复制代码













回复

使用道具 举报

63

主题

36

回帖

1927

积分

管理员

积分
1927
2019-7-18 18:14:30 显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 免费注册
关注微信