经典K线锤子止跌量化策略测试

蜗牛股票分析软件 snail007 225浏览 0评论

本文主要针对经典K线中的锤子止跌形态,用C++编程,采用策略为出现锤子止跌信号后第二天依开盘价买入,第三天收盘卖出,针对在过去2年内,分析A股3000股票并统计成功率和盈利情况。一则可以发现锤子止跌是否有效,二则可以不断优化策略找出更好的量化策略

1.针对锤子止跌线

锤子止跌定义:锤子线是K线经典形态的一种,其K线实体处于顶端,并带有较长的下影线。它一般出现在股价连续下跌的底部, 通常被认为是底部止跌反转的信号。实体与下影线比例越悬殊,则信号越具有参考价值。从K线形成分析,股票连续下跌后,空方占优,随后多方发起反攻,至收盘多方相对占优,形成下长影

以上为锤子止跌的理论依据,为了识别是锤子线还是吊顶线,我们可以使用均线来排除事实上的吊颈线

2.量化测试软件,这里使用本人开发的蜗牛股票分析软件蜗牛股票分析软件轻量式的股票分析软件,该软件功能较多,涉及早盘竞价选股,尾盘选股,基于波非那切6大类的综合选股,另外还有龙虎榜选股等

在这里我们主要使用新增加的量化功能来完成对策略的测试,目前该软件提供开源的策略插件SDK,下载地址是ccsdu2004/stockAddon

3.锤子量化策略的制定

满足一下2个条件:

  • 锤子线高点不超过10日均线,20日均线
  • 锤子线要求下长影不低于3倍实体且上长影很小

锤子线代码为:

bool isChuiZiK(const Stock& stock)
{
	float high = std::max(stock.current,stock.start);
	float low = std::min(stock.current,stock.start);

	if(!isEqual(stock.top,high))
		return false;

	if(!isEqual(stock.top,stock.current))
		return false;

	if(stock.top - stock.low <= 0.05f)
		return false;

    return (low - stock.low)*0.333f > high - low;
}

判断代码为:

			//低于10,21日均线
			if(std::get<1>(ma21[i]) > stocks[i].current && std::get<1>(ma10[i]) >= stocks[i].current)
			{
			    //锤子线
				bool ok = isChuiZiK(stocks[i]);
				if(ok)
				{
				    CHECK_AND_ADD(i+1);
				}
			}

全体代码为:

#include <utility>
#include "../../SnailStock/SnailAddonHost.h"
#include <iostream>

SnailAddonHost* addonHost = nullptr;
StockIndicator* indicator10 = nullptr;
StockIndicator* indicator21 = nullptr;
StockIndicator* indicator5 = nullptr;

extern "C" SNAIL_API_EXPORT SnailAddon* get_snail_interface(SnailAddonHost* host,int flag);

inline bool isHarden(const Stock& stock){return stock.increase > 9.6f;}
inline bool isEqual(float a,float b){return fabsf(a-b) <= 0.03f;}

QString maker_ = "蜗牛(snail007.com)";
QString desc = "锤子量化策略";

#define CHECK_AND_ADD(j)\
	int k = 0;\
	std::tuple<QString,float> buy(QString("下一交易日"),0.0f);\
	if(j < stocks.size())\
    {\
	    buy = std::make_tuple<QString,float>(stocks[j].date,stocks[j].start);\
    }\
    std::tuple<QString,float> sale(QString(""),0.0f);\
	if(j+1<stocks.size())\
    {\
	    k = 1;\
        sale = std::make_tuple<QString,float>(stocks[j+1].date,stocks[j+1].current);\
    }\
    addonHost->append(code,name,buy,sale,k,desc); 

bool isChuiZiK(const Stock& stock)
{
	float high = std::max(stock.current,stock.start);
	float low = std::min(stock.current,stock.start);

	if(!isEqual(stock.top,high))
		return false;

	if(!isEqual(stock.top,stock.current))
		return false;

	if(stock.top - stock.low <= 0.04f)
		return false;

    return (low - stock.low)*0.333 >= high - low;
}

class SnailAddonImpl : public SnailAddon
{
	void destroy(){delete this;}
	const QString maker()const{return maker_;}
	const QString version()const{return "1.0.0.4";}
	const QString description()const{return desc;}
	const QString tips()const{return "蜗牛标准策略";}
    void onRecevied(const QString& code,const QVector<Stock>& list)
	{
		const int span = 21;
	    if(list.size() <= span)
			return;

		indicator5->clear();
		indicator10->clear();
		indicator21->clear();
		auto set = addonHost->getStockList();
		QString name;
		if(set.contains(code))
		    name = set[code].name;

		CalcData ma10,ma21,vol5;
		foreach(Stock stock,list)
		{
			ma10.push_back(indicator10->update(stock));
			ma21.push_back(indicator21->update(stock));
			vol5.push_back(indicator5->update(stock));
		}

		QVector<Stock> stocks = list.mid(span);
		vol5 = vol5.mid(span);
		ma10 = ma10.mid(span);
		ma21 = ma21.mid(span);

		for(int i=0;i<stocks.size();i++)
		{
			//低于10,21日均线
			if(std::get<1>(ma21[i]) > stocks[i].current && std::get<1>(ma10[i]) >= stocks[i].current)
			{
			    //锤子线
				bool ok = isChuiZiK(stocks[i]);// && stocks[i].tradeVolume >= 2*std::get<1>(vol5[i]);
				if(ok)
				{
				    CHECK_AND_ADD(i+1);
				}
			}
		}
	}
private:
};

SnailAddon* get_snail_interface(SnailAddonHost* host,int flag)
{
	if(flag != SNAIL_ADDON_VERSION_INT || !host)
		return nullptr;

	addonHost = host;
	indicator10 = addonHost->createIndicator(SnailAddonHost::TAG_Indicator_Ma,10,0,0);
	indicator21 = addonHost->createIndicator(SnailAddonHost::TAG_Indicator_Ma,21,0,0);
	indicator5 = addonHost->createIndicator(SnailAddonHost::TAG_Indicator_VolMa,21,0,0);
    return new SnailAddonImpl();
}

代码还是很简单的,凡是会编程的基本能看懂

没有使用网上一些在线量化测试软件的原因是基于编程可以更好的控制量化粒度

数据量较大且需要分析历史数据,较为耗时

统计结果如下:

几乎55%的准确率,看来锤子止跌就飞浪得虚名也

在过去2年多内,共出现8459次买入信号,准确率54.88%左右,平均收益0.18%,离散度16

下面提高下锤子下长影的比重为4倍以上再分析下

结论如下:

能够发现准确率和收益率都有提升,可以说明锤子止跌线越标准,准确率越高

但是这个收益率还是不能接受,需要再次优化

首先看看那些高涨幅的买入点卖出点对应的K线形态

显然高涨幅的锤子止跌线都有高成交量,那就增加成交量方面的检查,当日成交量如果大于前5日2倍成交率则判断为优质锤子

再上结论

准确率60%多,平均收益1.46%,离散度1 .好家伙 结果让人难以置信

当然次数仅有105次也符合常理,凡是高准确率的形态其出现几率比较较低

以下为按日期排序

当然本策略还可以进一步优化

几个可以考虑优化的原则

1.今日开盘买入 明日收盘卖出,绝非较优策略,可以考虑从第二天的卖点出发,考虑优化

2.今日买入可以拉长卖出日期 或者破位后离场

3.出现锤子信号后可以考虑支撑位,压力位

4.单一策略无法通吃熊市和牛市,可以考虑分段对待

本策略3年今出现100多次,可以使用多策略混合模式,增加交易机会

本文经供参考,不足为买卖股票的凭证,如果有好的策略需要测试可以联系本人测试,也可以下载插件接口并自己操作

转载请注明:蜗牛股票分析软件 » 经典K线锤子止跌量化策略测试

发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址