指标举例ZigZag

一直以来想写一个类似ZigZag的指标,之前根据移动平均线写过一个类似的。发现图形比标准ZigZag似乎差了一点。最近干脆直接参考mql的源码移植了一个。程序跟mql机制非常像,所以移植起来很快就完成了。

由于比较常用所以做成了内置指标,分到了.h和.cpp文件:

#pragma once
#include "BI_IndicatorBase.h"
class BI_Indicator_ZigZag : public BI_IndicatorBase
{
public:
	int InpDepth;     // Depth
	int InpDeviation;  // Deviation
	int InpBackstep;   // Backstep

	double* ExtZigzagBuffer;
	double* ExtHighBuffer;
	double* ExtLowBuffer;

	int ExtLevel; // recounting's depth of extremums
	double Point;

public:
	/*cpp文件中必须实现的函数预定义*/
	void setInputs();
	void setProperties();
	void setLineBuffers();
	int onInit();
	int onCalculate();
	int onDeinit();

	//module function(s)
	int InitializeAll();

public:
	BI_Indicator_ZigZag();
	~BI_Indicator_ZigZag();
};


#include "stdafx.h"
#include "BI_Indicator_ZigZag.h"


BI_Indicator_ZigZag::BI_Indicator_ZigZag()
{
	InpDepth = 12;     // Depth
	InpDeviation = 5;  // Deviation
	InpBackstep = 3;   // Backstep

	ExtLevel = 3; // recounting's depth of extremums
}


BI_Indicator_ZigZag::~BI_Indicator_ZigZag()
{
}


/*functions that must be realized*/
void BI_Indicator_ZigZag::setInputs()
{
	input(InpDepth);
	input(InpDeviation);
	input(InpBackstep);
}

void BI_Indicator_ZigZag::setProperties()
{
	property_indicator_chart_window();

	property_shortname(L"BI_ZigZag");
	property_description(L"ZigZag");

	property_indicator_buffers(1);
	property_indicator_color(0, RGB(222, 17, 17));
	property_indicator_width(0, 1);
	property_indicator_style(0, 0);
	property_indicator_type(0, DRAW_LINE);

}

void BI_Indicator_ZigZag::setLineBuffers()
{
	line_buffer(ExtZigzagBuffer);
}


int BI_Indicator_ZigZag::onInit()
{
	IndicatorDigits(Digits);
	Point = 1 / pow(10.0, g_pDS->m_pipdigits);

	AddUserIndexBuffer(ExtHighBuffer);
	AddUserIndexBuffer(ExtLowBuffer);

	return 1;
}

int BI_Indicator_ZigZag::onCalculate()
{
	int i, limit, counterZ, whatlookfor = 0, counted_bars = IndicatorCounted();;
	int back, pos, lasthighpos = 0, lastlowpos = 0;
	double extremum;
	double curlow = 0.0, curhigh = 0.0, lasthigh = 0.0, lastlow = 0.0;

	//--- check for history and inputs
	if (Bars < InpDepth || InpBackstep >= InpDepth)
		return 0;

	if (counted_bars == 0)
		limit = InitializeAll();
	else
	{
		//--- find first extremum in the depth ExtLevel or 100 last bars
		i = counterZ = 0;
		while (counterZ<ExtLevel && i<100)
		{
			if (ExtZigzagBuffer[i] != EMPTY_VALUE)
				counterZ++;
			i++;
		}
		//--- no extremum found - recounting all from begin
		if (counterZ == 0)
			limit = InitializeAll();
		else
		{
			//--- set start position to found extremum position
			limit = i - 1;
			//--- what kind of extremum?
			if (ExtLowBuffer[i] != 0.0)
			{
				//--- low extremum
				curlow = ExtLowBuffer[i];
				//--- will look for the next high extremum
				whatlookfor = 1;
			}
			else
			{
				//--- high extremum
				curhigh = ExtHighBuffer[i];
				//--- will look for the next low extremum
				whatlookfor = -1;
			}
			//--- clear the rest data
			for (i = limit - 1; i >= 0; i--)
			{
				ExtZigzagBuffer[i] = EMPTY_VALUE;
				ExtLowBuffer[i] = 0.0;
				ExtHighBuffer[i] = 0.0;
			}
		}
	}


	//--- main loop      
	for (i = limit; i >= 0; i--)
	{
		//--- find lowest low in depth of bars
		extremum = 99999.99;
		for (int j = i; j < i + InpDepth; j++)
		{
			if (Low[j] < extremum) extremum = Low[j];
		}
		//extremum = Low[iLowest(NULL, 0, MODE_LOW, InpDepth, i)];
		//--- this lowest has been found previously
		if (extremum == lastlow)
			extremum = 0.0;
		else
		{
			//--- new last low
			lastlow = extremum;
			//--- discard extremum if current low is too high
			if (Low[i] - extremum>InpDeviation*Point)
				extremum = 0.0;
			else
			{
				//--- clear previous extremums in backstep bars
				for (back = 1; back <= InpBackstep; back++)
				{
					pos = i + back;
					if (ExtLowBuffer[pos] != 0 && ExtLowBuffer[pos]>extremum)
						ExtLowBuffer[pos] = 0.0;
				}
			}
		}
		//--- found extremum is current low
		if (Low[i] == extremum)
			ExtLowBuffer[i] = extremum;
		else
			ExtLowBuffer[i] = 0.0;
		//--- find highest high in depth of bars
		extremum = 0.0;
		for (int j = i; j < i + InpDepth; j++)
		{
			if (High[j] > extremum) extremum = High[j];
		}
		//extremum = High[iHighest(NULL, 0, MODE_HIGH, InpDepth, i)];
		//--- this highest has been found previously
		if (extremum == lasthigh)
			extremum = 0.0;
		else
		{
			//--- new last high
			lasthigh = extremum;
			//--- discard extremum if current high is too low
			if (extremum - High[i]>InpDeviation*Point)
				extremum = 0.0;
			else
			{
				//--- clear previous extremums in backstep bars
				for (back = 1; back <= InpBackstep; back++)
				{
					pos = i + back;
					if (ExtHighBuffer[pos] != 0 && ExtHighBuffer[pos]<extremum)
						ExtHighBuffer[pos] = 0.0;
				}
			}
		}
		//--- found extremum is current high
		if (High[i] == extremum)
			ExtHighBuffer[i] = extremum;
		else
			ExtHighBuffer[i] = 0.0;
	}
	//--- final cutting 
	if (whatlookfor == 0)
	{
		lastlow = 0.0;
		lasthigh = 0.0;
	}
	else
	{
		lastlow = curlow;
		lasthigh = curhigh;
	}
	for (i = limit; i >= 0; i--)
	{
		switch (whatlookfor)
		{
		case 0: // look for peak or lawn 
			if (lastlow == 0.0 && lasthigh == 0.0)
			{
				if (ExtHighBuffer[i] != 0.0)
				{
					lasthigh = High[i];
					lasthighpos = i;
					whatlookfor = -1;
					ExtZigzagBuffer[i] = lasthigh;
				}
				if (ExtLowBuffer[i] != 0.0)
				{
					lastlow = Low[i];
					lastlowpos = i;
					whatlookfor = 1;
					ExtZigzagBuffer[i] = lastlow;
				}
			}
			break;
		case 1: // look for peak
			if (ExtLowBuffer[i] != 0.0 && ExtLowBuffer[i]<lastlow && ExtHighBuffer[i] == 0.0)
			{
				ExtZigzagBuffer[lastlowpos] = EMPTY_VALUE;
				lastlowpos = i;
				lastlow = ExtLowBuffer[i];
				ExtZigzagBuffer[i] = lastlow;
			}
			if (ExtHighBuffer[i] != 0.0 && ExtLowBuffer[i] == 0.0)
			{
				lasthigh = ExtHighBuffer[i];
				lasthighpos = i;
				ExtZigzagBuffer[i] = lasthigh;
				whatlookfor = -1;
			}
			break;
		case -1: // look for lawn
			if (ExtHighBuffer[i] != 0.0 && ExtHighBuffer[i]>lasthigh && ExtLowBuffer[i] == 0.0)
			{
				ExtZigzagBuffer[lasthighpos] = EMPTY_VALUE;
				lasthighpos = i;
				lasthigh = ExtHighBuffer[i];
				ExtZigzagBuffer[i] = lasthigh;
			}
			if (ExtLowBuffer[i] != 0.0 && ExtHighBuffer[i] == 0.0)
			{
				lastlow = ExtLowBuffer[i];
				lastlowpos = i;
				ExtZigzagBuffer[i] = lastlow;
				whatlookfor = 1;
			}
			break;
		}
	}



	//--- done
	return Bars;

}

int BI_Indicator_ZigZag::onDeinit()
{
	return 1;
}

int BI_Indicator_ZigZag::InitializeAll()
{
	for (int i = 0; i < Bars; i++)
	{
		ExtZigzagBuffer[i] = EMPTY_VALUE;
		ExtHighBuffer[i] = 0.0;
		ExtLowBuffer[i] = 0.0;
	}

	return(Bars - InpDepth);
}

mql与这段c++的区别在于对于不绘制的点前者用0.0表示了,而本段程序中为EMPTY_VALUE。

Leave a Reply