基于K线形态锤子线的趋势跟踪策略

'''
策略原理:
  在下跌过程中,当某一日出现锤子线,意味着当天行情先继续下跌后出现大幅反弹,行情可能由此反转;
  由此以观察期均线识别趋势下跌,以下跌趋势中出现锤子线作为开仓信号;
  采用移动止损方式进行止损构建此策略;
  择时策略:
'''
import numpy as np
import pandas as pd
import tushare as ts
from matplotlib import pyplot as plt
from matplotlib import font_manager
my_font = font_manager.FontProperties(fname='C:/Windows/Fonts/simhei.ttf')

# 参数设置
code = 'hs300'         # 股票代码
start = '2018-01-01'   # 回测开始时间
end = '2020-04-24'     # 回测结束时间
body_size = 0.3        # k线实体长度与开盘价之比的 上限,即当日k线涨幅
head_size = 0.5        # k线上影线长度与k线下影线长度之比的 上限
tail_size = 2          # k线下影线长度与k线实体长度之比的 下限
length = 10            # 观察期时间长短
stoplose_trigger = 1   # 止损触发的几倍标准差
# 获取数据
stock = ts.get_k_data(code, start=start, end=end)[['date', 'open', 'close', 'high', 'low']]
# 数据准备
stock['ma'] = stock['close'].rolling(length).mean()
stock['std'] = stock['close'].rolling(length).std()
stock['pct_change'] = stock['close'].pct_change()
stock['yes_ma'] = stock['ma'].shift(1)
stock['yes_std'] = stock['std'].shift(1)
# 判断k线是否为锤子线
stock['head'] = stock['high'] - stock[['open', 'close']].max(axis=1)    # 上影线长度
stock['body'] = abs(stock['open'] - stock['close'])                     # 实体长度
stock['tail'] = stock[['open', 'close']].min(axis=1) - stock['low']     # 下影线长度
stock['head_cond'] = np.where(stock['tail'] == 0, False, stock['head'] / stock['tail'] < head_size)
stock['body_cond'] = np.where(stock['body'] / stock['open'] < body_size, 1, 0)
stock['tail_cond'] = np.where(stock['tail'] == 0, True, stock['tail'] / stock['body'] > tail_size)
stock['hammer'] = stock[['head_cond', 'body_cond', 'tail_cond']].all(axis=1)  # 锤子信号
stock['yes_hammer'] = stock['hammer'].shift(1)  # 昨天的锤子信号
# 交易策略***************************************
signal = 0   # 持仓记录,1代码有仓位,0代表空仓;
# 遍历每一天,前20天数据无效
for i in range(2*length, len(stock)):
    # 1. 持仓中
    if signal == 1:
        stoplose_price = max(stock.loc[i, 'yes_ma'] - stoplose_trigger * stock.loc[i, 'yes_std'],
                             long_open_price - long_open_delta)
        # 判断是否满足止损
        if stock.loc[i, 'low'] < stoplose_price:
            signal = 0
            # 当天收益计算
            stock.loc[i,'return'] = min(stock.loc[i, 'open'], stoplose_price) / stock.loc[i, 'open'] - 1
            stock.loc[i, 'signal'] = -1

        # 不满足止损条件,继续持仓的收益
        else:
            stock.loc[i, 'return'] = stock.loc[i, 'close'] / stock.loc[i-1, 'close'] - 1
            stock.loc[i, 'signal'] = 1

    # 2. 开仓触发条件
    else:
        # 判断前期是否下降趋势中
        if stock.loc[i-length, 'ma'] > stock.loc[i, 'ma']:
            # 判断是否有锤子信号
            if stock.loc[i, 'yes_hammer']:
                signal = 1
                # 开仓价格&标准差
                long_open_price = stock.loc[i, 'open']
                long_open_delta = stock.loc[i, 'yes_std']
                # 当天收益计算
                stock.loc[i, 'return'] = stock.loc[i, 'close'] / stock.loc[i, 'open'] - 1
                stock.loc[i, 'signal'] = 2
stock['signal'] = stock['signal'].fillna(0)
# 收益计算
stock['return'] = stock['return'].fillna(0)
stock['stock_return'] = (1 + stock['pct_change']).cumprod()
stock['strategy_return'] = (1 + stock['return']).cumprod()
print(stock)

# 画图
stock[['stock_return', 'strategy_return']].plot(figsize=(16,8))
plt.legend(loc=2)
plt.xticks(list(range(len(stock)))[::30], stock['date'][::30], rotation=45)
plt.show()

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值