请 [注册] 或 [登录]  | 返回主站

量化交易吧 /  数理科学 帖子:3352771 新帖:46

EMA均线的趋势效应与择时交易

有事您说话发表于:5 月 10 日 02:48回复(1)

指数平均数也叫EXPMA指标,它是一种趋向类指标,指数平均数指标是以指数式递减加权的移动平均。其构造原理是对股票收盘价进行算术平均,并根据计算结果来进行分析,用于判断价格未来走势的变动趋势。

原理:

与MACD指标、DMA指标相比,EXPMA指标由于其计算公式中着重考虑了价格当天(当期)行情的权重,因此指标自身的计算公式决定了作为一类趋势分析指标,它在使用中克服了MACD指标信号对于价格走势的滞后性。同时也在一定程度中消除了DMA指标在某些时候对于价格走势所产生的信号提前性,是一个非常有效的分析指标。

公式:

EXPMA=(当日或当期收盘价-上一日或上期EXPMA)/N 上一日或上期EXPMA,其中,首次上期EXPMA值为上一期收盘价,N为天数。

目的:

寻找出最符合沪深300指数的单EMA、双EMA、多EMA

导入需要模块

"""导入常用模块"""import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport datetimefrom jqdata import *from jqlib.technical_analysis import *from environment import * # 导入大树工作室开发的回测模块

沪深300价格与EMA示例

securirty = '000300.XSHG'EMA_data = []
HS_data = []
trade_date = get_trade_days(start_date= '2010-01-01', end_date= '2018-12-31')

HS_data = get_price(security='000300.XSHG', 
                  start_date='2010-1-1', 
                  end_date='2018-12-31', 
                  frequency='daily', 
                  fields=None, 
                  skip_paused=False, 
                  fq='pre')def get_ema(time_date):return EMA('000300.XSHG', check_date= time_date, timeperiod=25)[securirty]
EMA_data = list(map(get_ema, trade_date))
EMA_data = pd.Series(EMA_data, index= HS_data['close'].index)

plt.figure(figsize=(20, 9))
plt.plot(HS_data['close'], linewidth = '2')
plt.plot(EMA_data, linewidth = '2')
plt.title('沪深300指数从2010年到2018的价格曲线')
plt.legend(['指数价格', 'EMA均线'], loc=2)
plt.show()

output_4_0.png

由图可得知EMA与MA有相同之处,但比MA更敏感,选择最优的EMA对于趋势判断会有很大帮助,我们就来对比看看多EMA的情况。

plt.figure(figsize=(20, 9))

EMA_list = [15, 30, 45, 60, 75, 90, 105, 120, 135]for number in EMA_list:
    EMA_data = []for time_date in trade_date:
        EMA_value = EMA('000300.XSHG', check_date= time_date, timeperiod= number)[securirty]
        EMA_data.append(EMA_value)
    EMA_data = pd.Series(EMA_data, index= HS_data['close'].index) 
    EMA_data.plot(linewidth = '2')
plt.title('2010年到2018的多EMA曲线图')
plt.legend(EMA_list, loc=2)
plt.show()

output_6_0.png

单EMA均线择时效应研究

单EMA均线择时效应

理论:价格在EMA均线之上表示多头行情,价格在EMA均线之下表示空头行情——这种情况是否有效?接下来,做一个数据回测。

因为是做评估,所以这里选择了沪深300指数来交易。可能这有点让人接受不了,人有会说:“指数怎么能交易呢?”笔者是这么想的,对于指标的判断,放在个股上,有的适用,有的则不适用。因其股性的不同,倒不如测试代表标的集合的指数。虽然指数不可交易,但不妨碍我们对其历史数据进行分析。因此,笔者自行搭建了一个回测环境,在交易的时候,默认全仓交易,不考虑交易费用、滑点等不可控因素,所有的数据皆以收盘价为准,并且,成交量也不以每股计算,而是能成交多少算多少,这是为了充分使用资金的原因。因此,这里对数据的评估是存在一定的过拟合现象的。

为了排除这种过拟合现象,我们的应对方法是,当做出评估结果后,再重新写一个回测策略,对验证评估效果,这样的交叉验证可以最大程度的还原数据与评估结果之间的关系。

我们期望的交易模式如下:红圈表示买点,绿圈表示卖点。

securirty = '000300.XSHG'EMA_da = []
HS_da = []
trade_da = get_trade_days(start_date= '2017-01-01', end_date= '2018-12-31')

HS_da = get_price(security='000300.XSHG', 
                  start_date='2017-1-1', 
                  end_date='2018-12-31', 
                  frequency='daily', 
                  fields=None, 
                  skip_paused=False, 
                  fq='pre')
HS_da_close = HS_da['close']def get_ema(time_date):return EMA('000300.XSHG', check_date= time_date, timeperiod=15)[securirty]
EMA_da = list(map(get_ema, trade_da))
EMA_da = pd.Series(EMA_da, index= HS_da_close.index)

plt.figure(figsize=(20, 9))
plt.plot(HS_da_close, linewidth=2, color='orange')
plt.plot(EMA_da, linewidth=2, c='b')# 找出买点与卖点,分别用红绿圈画出for i in range(1, len(HS_da_close)):if HS_da_close[i-1] < EMA_da[i-1] and HS_da_close[i] > EMA_da[i]:
        plt.scatter(HS_da_close.index[i], EMA_da[i], color='', marker='o', edgecolors='r', s=300, linewidths=2)elif HS_da_close[i-1] > EMA_da[i-1] and HS_da_close[i] < EMA_da[i]:
        plt.scatter(HS_da_close.index[i], EMA_da[i], color='', marker='o', edgecolors='g', s=300, linewidths=2)

plt.title('沪深300指数从2017年到2018的25EMA买卖点示例图')
plt.legend(['收盘价', '25EMA均线'], loc=2)
plt.show()

output_9_0.png

接下来,将上述理念转化成交易策略,并查看其结果:

单组合单EMA均线择时回测效益

"""初始化以下内容"""context = Context() # 账户对象order = Order(context) # 下单对象trade = Trade(context, order) # 回测对旬context.start_date = '2010-01-01'context.end_date = '2018-12-31'context.universe = ['000300.XSHG']
context.base = '000300.XSHG'"""策略主体"""def handle(context, order):stock = context.universe[0]
    HS_da = get_price(security=stock, 
                      end_date= context.current_dt,
                      frequency= 'daily', 
                      fields= None, 
                      skip_paused= False, 
                      fq='pre',
                      count= 50)['close']

    EMA_da_2 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=15)[stock]
    EMA_da_1 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=15)[stock]if HS_da[-2] < EMA_da_2 and HS_da[-1] > EMA_da_1:
        order.buy(stock, HS_da[-1], context.cash // HS_da[-1])elif HS_da[-2] > EMA_da_2 and HS_da[-1] < EMA_da_1: if stock not in context.position.keys():returnorder.sell(stock, HS_da[-1], context.position[stock]['count'])"""执行策略"""trade.trade(handle)

output_12_1.png

构建多组合单EMA均线回测对比

trade_list = []
EMA_list = [15, 30, 45, 60, 75, 90, 105, 120, 135]for _EMA in EMA_list:# 策略结构context = Context()
    order = Order(context)
    trade = Trade(context, order)
    context.start_date = '2010-01-01'context.end_date = '2018-12-31'context.universe = ['000300.XSHG']
    context.base = '000300.XSHG'def handle(context, order):stock = context.universe[0]
        ema_count = _EMA
        HS_da = get_price(security=stock, 
                      end_date= context.current_dt,
                      frequency= 'daily', 
                      fields= None, 
                      skip_paused= False, 
                      fq='pre',
                      count= 150)['close']

        EMA_da_2 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=ema_count)[stock]
        EMA_da_1 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=ema_count)[stock]if HS_da[-2] < EMA_da_2 and HS_da[-1] > EMA_da_1:
            order.buy(stock, HS_da[-1], context.cash // HS_da[-1])elif HS_da[-2] > EMA_da_2 and HS_da[-1] < EMA_da_1: if stock not in context.position.keys():returnorder.sell(stock, HS_da[-1], context.position[stock]['count'])
    trade.trade(handle, False)
    trade_list.append(trade)# 展示Trade.show_ratio_compare('EMA', EMA_list, trade_list, 3, 3)

output_14_1.png

Trade.show_result('EMA', EMA_list, trade_list)

1.jpg

由上图数据表对比分析,符合沪深300指数的EMA值为30,即月线EMA。于熊市时候,策略收益图下跌的斜率明显低于其他EMA数值的策略,于牛市时候,策略收益图上涨的斜率会高于其他EMA数值的策略,而且对比其他指标,最大回撤、胜率、策略收益、年化收益排名同列于第一,说明EMA值30是有效的最优参数。

构建多组合单EMA均线趋势回测对比

从整体来看,EMA均线比较敏感,值越小开单数也越多,我们可以寻找它本身类似于MA均线的特性来运用于趋势判断来减少开单数,减少不必要的机会成本浪费。

EMA趋势判断逻辑:

EMA单均线判断,今日与隔日EMA均线判断,今日大于隔日为上升趋势,反之为下跌趋势。

EMA单均线判断,今日于一定间隔日EMA均线判断,斜率向上即为上升趋势,反之为下跌趋势。

单组合单EMA均线隔日趋势回测

"""初始化以下内容"""context = Context() # 账户对象order = Order(context) # 下单对象trade = Trade(context, order) # 回测对旬context.start_date = '2010-01-01'context.end_date = '2018-12-31'context.universe = ['000300.XSHG']
context.base = '000300.XSHG'"""策略主体"""def handle(context, order):stock = context.universe[0]
    HS_da = get_price(security=stock, 
                      end_date= context.current_dt,
                      frequency= 'daily', 
                      fields= None, 
                      skip_paused= False, 
                      fq='pre',
                      count= 50)['close']
    EMA_da_2 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=30)[stock]
    EMA_da_1 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=30)[stock]if HS_da[-2] < EMA_da_2 and HS_da[-1] > EMA_da_1:if EMA_da_1 < EMA_da_2:returnorder.buy(stock, HS_da[-1], context.cash // HS_da[-1])elif HS_da[-2] > EMA_da_2 and HS_da[-1] < EMA_da_1: if stock not in context.position.keys():returnorder.sell(stock, HS_da[-1], context.position[stock]['count'])"""执行策略"""trade.trade(handle)

output_20_1.png

数据回测是以EMA均线30为基础,从数据的指标对比,策略各方面有明显的改善,说明趋势判断是有效的。但是,单以当前一个EMA均线下去对比,是不能够完全突显出效果的,我们就以多个数据来对比。

多组合单EMA均线隔日趋势回测

trade_list = []
EMA_list = [15, 30, 45, 60, 75, 90, 105, 120, 135]for _EMA in EMA_list:# 策略结构context = Context()
    order = Order(context)
    trade = Trade(context, order)
    context.start_date = '2010-01-01'context.end_date = '2018-12-31'context.universe = ['000300.XSHG']
    context.base = '000300.XSHG'def handle(context, order):stock = context.universe[0]
        ema_count = _EMA
        HS_da = get_price(security=stock, 
                      end_date= context.current_dt,
                      frequency= 'daily', 
                      fields= None, 
                      skip_paused= False, 
                      fq='pre',
                      count= 10)['close']
        EMA_da_2 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=ema_count)[stock]
        EMA_da_1 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=ema_count)[stock]if HS_da[-2] < EMA_da_2 and HS_da[-1] > EMA_da_1:if EMA_da_1 < EMA_da_2:returnorder.buy(stock, HS_da[-1], context.cash // HS_da[-1])elif HS_da[-2] > EMA_da_2 and HS_da[-1] < EMA_da_1: if stock not in context.position.keys():returnorder.sell(stock, HS_da[-1], context.position[stock]['count'])
    trade.trade(handle, False)
    trade_list.append(trade)# 展示Trade.show_ratio_compare('EMA', EMA_list, trade_list, 3, 3)

output_23_1.png

Trade.show_result('EMA', EMA_list, trade_list)

1.jpg

综合上面所有数据来看,EMA均线参数在:30、105、90的取值最为突出,但是临近的EMA均线对比做趋势还是有弊端的,大周期下的小周期会影响到当前的趋势条件。
因此,我们就借用一个间隔跨度来测试数据,取得一个比较能接受的数值来过滤掉大周期下的小周期。

单组合单EMA均线间隔趋势回测

"""初始化以下内容"""context = Context() # 账户对象order = Order(context) # 下单对象trade = Trade(context, order) # 回测对旬context.start_date = '2010-01-01'context.end_date = '2018-12-31'context.universe = ['000300.XSHG']
context.base = '000300.XSHG'"""策略主体"""def handle(context, order):stock = context.universe[0]
    HS_da = get_price(security=stock, 
                      end_date= context.current_dt,
                      frequency= 'daily', 
                      fields= None, 
                      skip_paused= False, 
                      fq='pre',
                      count= 50)['close']

    EMA_da_2 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=30)[stock]
    EMA_da_1 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=30)[stock]
    EMA_da_30 = EMA('000300.XSHG', check_date= HS_da.index[-30], timeperiod=30)[stock]if HS_da[-2] < EMA_da_2 and HS_da[-1] > EMA_da_1:if EMA_da_1 < EMA_da_30:returnorder.buy(stock, HS_da[-1], context.cash // HS_da[-1])elif HS_da[-2] > EMA_da_2 and HS_da[-1] < EMA_da_1: if stock not in context.position.keys():returnorder.sell(stock, HS_da[-1], context.position[stock]['count'])"""执行策略"""trade.trade(handle)

output_27_1.png

数据回测是以EMA均线30为基础,日间隔为30,从数据的指标对比,趋势效应加强了策略各方面,收益率的增长0.3535,夏普比率增长0.8311,但是回撤增长0.011,虽然加强了策略,依旧存在有的不足,我们需要找出最优的日间隔。

多组合单EMA均线间隔趋势回测对比

_list = []
trade_list = []
EMA_list = [15, 30, 45, 60, 75, 90, 105, 120, 135]
parmas = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]for _EMA in EMA_list:for pam in parmas:# 策略结构context = Context()
        order = Order(context)
        trade = Trade(context, order)
        context.start_date = '2010-01-01'context.end_date = '2018-12-31'context.universe = ['000300.XSHG']
        context.base = '000300.XSHG'_list.append(str(_EMA) ',' str(pam))def handle(context, order):stock = context.universe[0]
            ema_count = _EMA
            HS_da = get_price(security=stock, 
                          end_date= context.current_dt,
                          frequency= 'daily', 
                          fields= None, 
                          skip_paused= False, 
                          fq='pre',
                          count= 5*pam)['close']
            EMA_da_2 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=ema_count)[stock]
            EMA_da_1 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=ema_count)[stock]
            EMA_da_parma = EMA('000300.XSHG', check_date= HS_da.index[-pam], timeperiod=ema_count)[stock]if HS_da[-2] < EMA_da_2 and HS_da[-1] > EMA_da_1:if EMA_da_1 < EMA_da_parma:returnorder.buy(stock, HS_da[-1], context.cash // HS_da[-1])elif HS_da[-2] > EMA_da_2 and HS_da[-1] < EMA_da_1: if stock not in context.position.keys():returnorder.sell(stock, HS_da[-1], context.position[stock]['count'])
        trade.trade(handle, False)
        trade_list.append(trade)# 展示Trade.show_all_ratio('EMA', EMA_list, trade_list)

output_30_1.png

Trade.show_result('EMA', _list, trade_list)

1.jpg

EMA多数据以及日间隔参数回测数据如上,其告诉我们EMA均线30与日间隔参数70是最优搭配,而EMA均线30恰恰是我们曾经单EMA均线历史回测的最优选择之一,间隔70日参数基本是搭配了周期趋势,过滤部分小周期,让策略更加有效。

双EMA均线择时效应研究

单EMA均线最优参数以及趋势间隔参数,从实际的运用出发,并不能满足于当前市场的指标。因此,双EMA均线也是必不可少的一部分,所谓“双剑合璧”, 在市场中也能起到互相扶持作用。

单组合双EMA均线择时回测效益

trade_list = []
EMA_list = [(15, 30)]for _EMA in EMA_list:# 策略结构context = Context()
    order = Order(context)
    trade = Trade(context, order)
    context.start_date = '2010-01-01'context.end_date = '2018-12-31'context.universe = ['000300.XSHG']
    context.base = '000300.XSHG'def handle(context, order):stock = context.universe[0]
        ema_count = _EMA
        HS_da = get_price(security=stock, 
                      end_date= context.current_dt,
                      frequency= 'daily', 
                      fields= None, 
                      skip_paused= False, 
                      fq='pre',
                      count= 35)['close']

        EMA_da_11 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=ema_count[0])[stock]
        EMA_da_12 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=ema_count[0])[stock]

        EMA_da_21 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=ema_count[1])[stock]
        EMA_da_22 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=ema_count[1])[stock]if EMA_da_12 < EMA_da_22 and EMA_da_11 > EMA_da_21:
            order.buy(stock, HS_da[-1], context.cash // HS_da[-1])elif EMA_da_12 > EMA_da_22 and EMA_da_11 < EMA_da_21: if stock not in context.position.keys():returnorder.sell(stock, HS_da[-1], context.position[stock]['count'])
    trade.trade(handle)

output_35_1.png

构建多组合双EMA均线回测对比

trade_list = []
EMA_list = [(5, 15), (15, 30), (30, 45), (45, 60), (60, 75), (75, 90), (90, 105), (105, 120), (120, 135)]for _EMA in EMA_list:# 策略结构context = Context()
    order = Order(context)
    trade = Trade(context, order)
    context.start_date = '2010-01-01'context.end_date = '2018-12-31'context.universe = ['000300.XSHG']
    context.base = '000300.XSHG'def handle(context, order):stock = context.universe[0]
        ema_count = _EMA
        HS_da = get_price(security=stock, 
                      end_date= context.current_dt,
                      frequency= 'daily', 
                      fields= None, 
                      skip_paused= False, 
                      fq='pre',
                      count= 140)['close']

        EMA_da_11 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=ema_count[0])[stock]
        EMA_da_12 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=ema_count[0])[stock]

        EMA_da_21 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=ema_count[1])[stock]
        EMA_da_22 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=ema_count[1])[stock]if EMA_da_12 < EMA_da_22 and EMA_da_11 > EMA_da_21:
            order.buy(stock, HS_da[-1], context.cash // HS_da[-1])elif EMA_da_12 > EMA_da_22 and EMA_da_11 < EMA_da_21: if stock not in context.position.keys():returnorder.sell(stock, HS_da[-1], context.position[stock]['count'])
    trade.trade(handle, False)
    trade_list.append(trade)# 展示Trade.show_ratio_compare('EMA', EMA_list, trade_list, 3, 3)

output_37_1.png

Trade.show_result('EMA', EMA_list, trade_list)

1.jpg

双EMA均线回测数据表,给我们(15,30)EMA均线为当前均线搭配组合中最优的搭配。前期数据的老伙伴参数30依旧存在,所以我们可以进一步认可30数值在EMA均线中的作用还是有一定影响力的。接下来我们需要加上趋势的对比,来验证是否有优化情况。

构建多组合双EMA均线趋势回测对比

单组合双EMA均线间隔趋势回测对比

_list = []
trade_list = []
EMA_list = [(15, 30)]
parmas = [70]for _EMA in EMA_list:for pam in parmas:# 策略结构context = Context()
        order = Order(context)
        trade = Trade(context, order)
        context.start_date = '2010-01-01'context.end_date = '2018-12-31'context.universe = ['000300.XSHG']
        context.base = '000300.XSHG'_list.append(str(_EMA) ',' str(pam))def handle(context, order):stock = context.universe[0]
            ema_count = _EMA
            HS_da = get_price(security=stock, 
                          end_date= context.current_dt,
                          frequency= 'daily', 
                          fields= None, 
                          skip_paused= False, 
                          fq='pre',
                          count= 140)['close']
            EMA_da_11 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=ema_count[0])[stock]
            EMA_da_12 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=ema_count[0])[stock]

            EMA_da_21 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=ema_count[1])[stock]
            EMA_da_22 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=ema_count[1])[stock]

            EMA_da_pam = EMA('000300.XSHG', check_date= HS_da.index[-pam], timeperiod=ema_count[1])[stock]if EMA_da_12 < EMA_da_22 and EMA_da_11 > EMA_da_21:if EMA_da_21 < EMA_da_pam:returnorder.buy(stock, HS_da[-1], context.cash // HS_da[-1])elif EMA_da_12 > EMA_da_22 and EMA_da_11 < EMA_da_21: if stock not in context.position.keys():returnorder.sell(stock, HS_da[-1], context.position[stock]['count'])

        trade.trade(handle)

output_42_1.png

多组合双EMA均线间隔趋势回测对比

_list = []
trade_list = []
EMA_list = [(5, 15), (15, 30), (30, 45), (45, 60), (60, 75), (75, 90), (90, 105), (105, 120), (120, 135)]
parmas = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]for _EMA in EMA_list:for pam in parmas:# 策略结构context = Context()
        order = Order(context)
        trade = Trade(context, order)
        context.start_date = '2010-01-01'context.end_date = '2018-12-31'context.universe = ['000300.XSHG']
        context.base = '000300.XSHG'_list.append(str(_EMA) ',' str(pam))def handle(context, order):stock = context.universe[0]
            ema_count = _EMA
            HS_da = get_price(security=stock, 
                          end_date= context.current_dt,
                          frequency= 'daily', 
                          fields= None, 
                          skip_paused= False, 
                          fq='pre',
                          count= 140)['close']
            EMA_da_11 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=ema_count[0])[stock]
            EMA_da_12 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=ema_count[0])[stock]

            EMA_da_21 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=ema_count[1])[stock]
            EMA_da_22 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=ema_count[1])[stock]

            EMA_da_pam = EMA('000300.XSHG', check_date= HS_da.index[-pam], timeperiod=ema_count[1])[stock]if EMA_da_12 < EMA_da_22 and EMA_da_11 > EMA_da_21:if EMA_da_21 < EMA_da_pam:returnorder.buy(stock, HS_da[-1], context.cash // HS_da[-1])elif EMA_da_12 > EMA_da_22 and EMA_da_11 < EMA_da_21: if stock not in context.position.keys():returnorder.sell(stock, HS_da[-1], context.position[stock]['count'])

        trade.trade(handle, False)
        trade_list.append(trade)# 展示Trade.show_all_ratio('EMA', EMA_list, trade_list)

output_44_3.png

Trade.show_result('EMA', _list, trade_list)

1.jpg

在双EMA均线与趋势组合的数据中,开始出现了不同的情况,组合(5, 15),(15, 30)排头,然后斜率也各自不同,前者搭配了80-90,后者搭配了20-30的间隔参数。组合的数值会让人想到倍数情况,然后斜率也出现同样的思考,从EMA均线的原理来思考,两个组合的斜率搭配是不是有点相似,但是开单数却完全不同,这个原因是在于EMA的敏感问题,可以说(5, 15)属于高频交易类型,也就是积进,而(15, 30)属于中等频交易类型。这样选择,就要看个人的风格和喜好了。

多EMA均线择时效应研究

双EMA均线数据对比有利于研究市场,自然会有多均线情况,短、中、长均线搭配,大多数人会比较喜好,短线情绪,中线风控,长线趋势。我们就来看看,会有什么样的变化。

单组合多EMA均线择时回测效益

trade_list = []
EMA_list = [(5, 15, 30)]for _EMA in EMA_list:# 策略结构context = Context()
    order = Order(context)
    trade = Trade(context, order)
    context.start_date = '2010-01-01'context.end_date = '2018-12-31'context.universe = ['000300.XSHG']
    context.base = '000300.XSHG'def handle(context, order):stock = context.universe[0]
        ema_count = _EMA
        HS_da = get_price(security=stock, 
                      end_date= context.current_dt,
                      frequency= 'daily', 
                      fields= None, 
                      skip_paused= False, 
                      fq='pre',
                      count= 35)['close']

        EMA_da_11 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=ema_count[0])[stock]
        EMA_da_12 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=ema_count[0])[stock]

        EMA_da_21 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=ema_count[1])[stock]
        EMA_da_22 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=ema_count[1])[stock]

        EMA_da_31 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=ema_count[2])[stock]
        EMA_da_32 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=ema_count[2])[stock]if EMA_da_12 < EMA_da_22 and EMA_da_11 > EMA_da_21:if EMA_da_21 < EMA_da_31: returnorder.buy(stock, HS_da[-1], context.cash // HS_da[-1])elif EMA_da_12 > EMA_da_22 and EMA_da_11 < EMA_da_21: if stock not in context.position.keys():returnorder.sell(stock, HS_da[-1], context.position[stock]['count'])
    trade.trade(handle)
2019-02-23 17:31:43.469758,回测完毕,用时0:00:21.368093

output_49_1.png

构建多组合多EMA均线择时回测效益

trade_list = []
EMA_list = [(5, 15, 30), (15, 30, 45), (30, 45, 60), (45, 60, 75), (60, 75, 90), (75, 90, 105), (90, 105, 120), (105, 120, 135), (120, 135, 150)]for _EMA in EMA_list:# 策略结构context = Context()
    order = Order(context)
    trade = Trade(context, order)
    context.start_date = '2010-01-01'context.end_date = '2018-12-31'context.universe = ['000300.XSHG']
    context.base = '000300.XSHG'def handle(context, order):stock = context.universe[0]
        ema_count = _EMA
        HS_da = get_price(security=stock, 
                      end_date= context.current_dt,
                      frequency= 'daily', 
                      fields= None, 
                      skip_paused= False, 
                      fq='pre',
                      count= 160)['close']

        EMA_da_11 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=ema_count[0])[stock]
        EMA_da_12 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=ema_count[0])[stock]

        EMA_da_21 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=ema_count[1])[stock]
        EMA_da_22 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=ema_count[1])[stock]

        EMA_da_31 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=ema_count[2])[stock]
        EMA_da_32 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=ema_count[2])[stock]if EMA_da_12 < EMA_da_22 and EMA_da_11 > EMA_da_21:if EMA_da_21 < EMA_da_31: returnorder.buy(stock, HS_da[-1], context.cash // HS_da[-1])elif EMA_da_12 > EMA_da_22 and EMA_da_11 < EMA_da_21: if stock not in context.position.keys():returnorder.sell(stock, HS_da[-1], context.position[stock]['count'])
    trade.trade(handle, False)
    trade_list.append(trade)# 展示Trade.show_ratio_compare('EMA', EMA_list, trade_list, 3, 3)
2019-02-23 17:32:58.042600,回测完毕,用时0:00:20.4705362019-02-23 17:33:19.926138,回测完毕,用时0:00:21.8833682019-02-23 17:33:43.443715,回测完毕,用时0:00:23.5174232019-02-23 17:34:07.823422,回测完毕,用时0:00:24.3795482019-02-23 17:34:32.905529,回测完毕,用时0:00:25.0819362019-02-23 17:34:59.589667,回测完毕,用时0:00:26.683975
/home/jquser/指标研究/environment.py:190: RuntimeWarning: divide by zero encountered in double_scalars  return abs(ratio[ratio > 0].sum()/ratio[ratio < 0].sum())
2019-02-23 17:35:27.066525,回测完毕,用时0:00:27.4767032019-02-23 17:35:55.787378,回测完毕,用时0:00:28.7207022019-02-23 17:36:24.890741,回测完毕,用时0:00:29.103209

output_51_3.png

Trade.show_result('EMA', EMA_list, trade_list)

1.jpg

多EMA均线组合数据表明,(15, 30, 45)为当前组合的最优组合,可以看见老战友依旧还没战死,这是非常可喜的一个事情。整体数据与双EMA均线组合对比,最亮眼的是盈亏比数据,有明显的提升。

构建多组合多EMA均线趋势回测对比

单组合多EMA均线间隔趋势回测对比

_list = []
trade_list = []
EMA_list = [(5, 15, 30)]
parmas = [70]for _EMA in EMA_list:for pam in parmas:# 策略结构context = Context()
        order = Order(context)
        trade = Trade(context, order)
        context.start_date = '2010-01-01'context.end_date = '2018-12-31'context.universe = ['000300.XSHG']
        context.base = '000300.XSHG'_list.append(str(_EMA) ',' str(pam))def handle(context, order):stock = context.universe[0]
            ema_count = _EMA
            HS_da = get_price(security=stock, 
                          end_date= context.current_dt,
                          frequency= 'daily', 
                          fields= None, 
                          skip_paused= False, 
                          fq='pre',
                          count= 140)['close']

            EMA_da_11 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=ema_count[0])[stock]
            EMA_da_12 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=ema_count[0])[stock]

            EMA_da_21 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=ema_count[1])[stock]
            EMA_da_22 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=ema_count[1])[stock]

            EMA_da_31 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=ema_count[2])[stock]
            EMA_da_32 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=ema_count[2])[stock]

            EMA_da_pam = EMA('000300.XSHG', check_date= HS_da.index[-pam], timeperiod=ema_count[1])[stock]if EMA_da_12 < EMA_da_22 and EMA_da_11 > EMA_da_21:if EMA_da_21 < EMA_da_pam or EMA_da_21 < EMA_da_31:returnorder.buy(stock, HS_da[-1], context.cash // HS_da[-1])elif EMA_da_12 > EMA_da_22 and EMA_da_11 < EMA_da_21: if stock not in context.position.keys():returnorder.sell(stock, HS_da[-1], context.position[stock]['count'])

        trade.trade(handle)
2019-02-23 17:38:42.753355,回测完毕,用时0:00:23.896671

output_56_1.png

多组合多EMA均线间隔趋势回测对比

_list = []
trade_list = []
EMA_list = [(5, 15, 30), (15, 30, 45), (30, 45, 60), (45, 60, 75), (60, 75, 90), (75, 90, 105), (90, 105, 120), (105, 120, 135), (120, 135, 150)]
parmas = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]for _EMA in EMA_list:for pam in parmas:# 策略结构context = Context()
        order = Order(context)
        trade = Trade(context, order)
        context.start_date = '2010-01-01'context.end_date = '2018-12-31'context.universe = ['000300.XSHG']
        context.base = '000300.XSHG'_list.append(str(_EMA) ',' str(pam))def handle(context, order):stock = context.universe[0]
            ema_count = _EMA
            HS_da = get_price(security=stock, 
                          end_date= context.current_dt,
                          frequency= 'daily', 
                          fields= None, 
                          skip_paused= False, 
                          fq='pre',
                          count= 140)['close']

            EMA_da_11 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=ema_count[0])[stock]
            EMA_da_12 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=ema_count[0])[stock]

            EMA_da_21 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=ema_count[1])[stock]
            EMA_da_22 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=ema_count[1])[stock]

            EMA_da_31 = EMA('000300.XSHG', check_date= HS_da.index[-1], timeperiod=ema_count[2])[stock]
            EMA_da_32 = EMA('000300.XSHG', check_date= HS_da.index[-2], timeperiod=ema_count[2])[stock]

            EMA_da_pam = EMA('000300.XSHG', check_date= HS_da.index[-pam], timeperiod=ema_count[1])[stock]if EMA_da_12 < EMA_da_22 and EMA_da_11 > EMA_da_21:if EMA_da_21 < EMA_da_pam or EMA_da_21 < EMA_da_31:returnorder.buy(stock, HS_da[-1], context.cash // HS_da[-1])elif EMA_da_12 > EMA_da_22 and EMA_da_11 < EMA_da_21: if stock not in context.position.keys():returnorder.sell(stock, HS_da[-1], context.position[stock]['count'])

        trade.trade(handle, False)
        trade_list.append(trade)# 展示Trade.show_all_ratio('EMA', EMA_list, trade_list)

output_58_3.png

Trade.show_result('EMA', _list, trade_list)

2.jpg

在多EMA均线与趋势组合的数据中,无独有偶,出现了特殊情况,组合(5, 15, 30),(15, 30,45)排头,然后斜率依旧为80-90与20-30的间隔参数。多个数据表明,30的数值在EMA均线中地位比较显赫。搭配的多EMA均线组合在开单方面,大大减少,在盈亏比中,提高也大,回撤也有一定程度的减小,它使得EMA均线在应对市场的时候,更沉稳了。

全部回复

0/140

量化课程

    移动端课程