个人量化:锤子线策略

本文介绍了锤子线策略的基本原理,包括K线部位定义、锤子线特征、策略背后的市场含义和止损条件。在下跌趋势中,锤子线的出现被视为可能的反转信号,结合移动止损来构建交易策略。该策略适用于下跌行情,要求锤子线的下影线至少是实体的两倍长,且实体较小。止损条件基于平均价格和标准差。
摘要由CSDN通过智能技术生成

基本原理


1.1 K线部位定义:


     实体:某一根K线开盘价和收盘价之间部分;  
    上影线:某一根K线最高价到实体上端的部分;  
    下影线:某一根K线最低价到实体下端的部分;


1.2 锤子线定义  


   实体处于整个价格区间上端,实体颜色本身不影响;  
   下影线长度至少达到实体高度的2倍;  
   上影线很短;


1.3 策略原理  


在下跌过程中,当某一日出现锤子线,意味着当天行情先继续下跌后出现大幅反弹,行情可能由此反转; 
由此以观察期均线识别趋势下跌,以下跌趋势中出现锤子线作为开仓信号;  
采用移动止损方式进行止损构建此策略;


1.4 止损条件  


当天最低价 < max(均价-观察期内一定倍数的标准差,开仓价-开仓时标准差);


1.5 形态要点:    


在出现锤头线(锤子线)之前,股价需经过一段时间的下跌后,处于下跌趋势中,此时出现此形态才具有参考意义;  
锤头实体越小,下影线越长,止跌作用就越明显,参考价值越大;

代码:

股票数据可以到这里下载:Kylin的开放家园

import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt

pd.set_option('expand_frame_repr', False)  # 当列太多时不换行
pd.set_option('display.max_rows', 5000)  # 最多显示数据的行数
pd.set_option('display.unicode.ambiguous_as_wide', True)
pd.set_option('display.unicode.east_asian_width', True)

stock_code = 'sh600624'  # 股票代码
body_size = 0.03         # 表示锤子实体大小上限,基准为当日开盘价,实体不能太大,波动范围限制在3%;
head_size = 0.5          # 表示锤子上影线长度上限,基准为下影线长度,上影线要短一点,不能超过下影线的的一半;
tail_size = 2            # 表示下影线与实体大小比值,下影线要大于实体两倍;
length = 10              # 表示观察期时间长短;
stoplose_trigger = 1     # 表示当价格偏离均线满足几倍标准差时止损

data = pd.read_csv(r'D:\stock_data\%s.csv' % stock_code,
                 encoding='gbk', skiprows=1, parse_dates=['交易日期'])

data.sort_index(ascending=True, inplace=True)

data.reset_index(inplace=True)        # 把索引设置成为默认;为了后面交易策略逻辑循环更方便一些;

data['pct_change'] = data['收盘价'].pct_change()
data['ma'] = data['收盘价'].rolling(length).mean()
data['std'] = data['收盘价'].rolling(length).std()
del data['成交量']
del data['流通市值']
del data['总市值']

# 由于实盘中当天的日线级别参考指标未实现,因此使用昨日参考指标指导当日交易,避免未来函数;
data['yes_ma'] = data['ma'].shift(1)          # 昨天的mean和昨天的std;
data['yes_std'] = data['std'].shift(1)

# 识别锤子形态
# 计算实体,上影线,下影线
data['body'] = abs(data['开盘价'] - data['收盘价'])   # 计算K线实体;
data['head'] = data['最高价'] - data[['开盘价', '收盘价']].max(axis=1)  # 计算上影线,按行计算
data['tail'] = data[['开盘价', '收盘价']].min(axis=1) - data['最低价']   # 计算下影线

# 判断K线各部分是否符合锤子线要求
data['body_cond'] = np.where(data['body']/data['开盘价'] < body_size, 1, 0)  # 实体的大小比开盘价要小于3%,K线实体不能太大;
data['head_cond'] = np.where(data['tail'] == 0, False, data['head'] / data['tail'] < head_size)   # 上影线不能比下影线的一半长;
# 当尾部长度为0,为防止判断除法报错,两步判断;
# data['head_cond'] = np.where(data['head']/data['tail'] < head_size, 1, 0)   有可能tail = 0
data['tail_cond'] = np.where(data['body'] == 0, True, (data['tail']/data['body']) > tail_size)

# 判断K线形态是否符合锤子线
data['hammer'] = data[['head_cond', 'body_cond', 'tail_cond']].all(axis=1)  # 同时满足以上三个条件才是锤子K线;

# 由于实盘中当天的日线级别参考指标未实现,因此应根据昨日是否满足锤子形态要求作为开仓信号
data['yes_hammer'] = data['hammer'].shift(1)

# 编写交易逻辑——循环法
flag = 0  # 持仓记录,1代码有仓位,0代表空仓;
for i in range(2 * length, len(data)):  # 从20天开始计算,因为前期数据无效;
    # 如果已持仓,判断是否止损
    if flag == 1:
        stoplose_price = max(data.loc[i, 'yes_ma'] - stoplose_trigger * data.loc[i, 'yes_std'],
                             long_open_price - long_open_delta)
        # 当天价格低于止损价,则进行止损,一个是移动止损,一个是开仓时候的开仓和开仓价-1倍标准差;
        if data.loc[i, '最低价'] < stoplose_price:  # 接下来要做的都是止损的操作;
            flag = 0
            #             data.loc[i, 'return'] = min(data.loc[i, 'open'], stoplose_price)/data.loc[i-1, 'close'] - 1
            # 计算清盘当天的收益;取min是因为,如果当天开盘价就小于了止损价,那么我们就要以开盘价就止损;
            # 不然会导致策略收益高估;
            # 收益计算时要除以前一天的收盘价;
            data.loc[i, 'return'] = stoplose_price / data.loc[i - 1, '收盘价'] - 1

            data.loc[i, 'trade_mark'] = -10  # 表示当天持仓并进行平仓,记录自己当天交易操作,平仓:-10;
            # 开仓是10;持仓为1,方便查阅;

        # 如果不满足止损条件,则继续持仓
        else:
            data.loc[i, 'return'] = data.loc[i, '收盘价'] / data.loc[i - 1, '收盘价'] - 1
            data.loc[i, 'trade_mark'] = 1  # 表示当天持仓

    # 如果未持仓,判断是否进行开仓
    else:
        # 判断是否为下降趋势,平均重心是下降的;锤子线开仓要满足形态和下降趋势;
        if data.loc[i - length, 'yes_ma'] > data.loc[i, 'yes_ma']:
            # 判断是否符合锤子形态
            if data.loc[i, 'yes_hammer']:
                # 更改持仓标记
                flag = 1
                # 记录开仓时开仓价格及标准差:是为了做固定止损;
                long_open_price = data.loc[i, '开盘价']
                long_open_delta = data.loc[i, 'yes_std']
                # 计算当天收益率
                data.loc[i, 'return'] = data.loc[i, '收盘价'] / data.loc[i, '开盘价'] - 1  # 以产生信号之后的第二天开盘价开仓;
                data.loc[i, 'trade_mark'] = 10  # 表示当天开仓
                # 当天开仓之后不进行平仓判断

# 计算策略收益率
data['return'].fillna(0, inplace=True)  # 对大循环中未处理的:既没有持仓,也不满足开仓条件的日期进行处理,则让这些天的return都等于0;
data['strategy_return'] = (data['return'] + 1).cumprod()
data['stock_return'] = (data['pct_change'] + 1).cumprod()

# 绘图
matplotlib.style.use('ggplot')
fig = plt.figure(figsize=(10, 5))
ax = fig.add_subplot(1, 1, 1)
ax.plot(data.stock_return, label='stock return')
ax.plot(data.strategy_return, label='strategy return')
plt.title(stock_code)
plt.legend()
plt.show()

# print(data.tail(10))
# print(data['hammer'].tail())


绘图结果:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaozi4120

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值