指标名称:砖块图
版本:MT4 ver. 1.16
最近很多朋友问我有没有MT4砖块图,安排!
砖块图(Renko Charts)是一种价格图表,最早由日本开发,后来由Steven Nison在其著作《Beyond Candlesticks》中向美国交易者介绍。该图表的名称源自单词“renga”,意思是“砖”,因为它通过类似堆叠砖块的方式来展示价格变动。
什么是砖块图表指标?
为了有效绘制砖块图,交易者需要使用砖块图指标,该指标通过砖块图方法自动呈现价格走势。
传统的价格图表根据时间顺序展示价格变化,y轴表示价格,x轴表示时间段,时间单位可以是分钟、小时、天等。而砖块图则完全忽视时间,仅关注价格变化。它通过“砖块”表示每一单位的价格波动,从而有效指示市场趋势和动量。
砖块图表指标如何工作?
砖块图表使用“砖块”表示每单位价格波动。此指标默认使用蓝砖表示价格上涨。
例如,若每块砖代表40点的价格变动,当价格上涨40点时,砖块图会绘制一块蓝砖;如果价格上涨80点,则绘制两块蓝砖;反之,若价格下跌80点或更多,则绘制两块红砖。
交易者可以根据不同的货币对和时间范围修改每块砖代表的点数或点数阈值。
砖块图的颜色变化和方向变动可以帮助交易者判断趋势的逆转。当砖块图开始绘制蓝色砖块时,表示上升趋势的开始,交易者可以选择在此时买入;当砖块图绘制红色砖块时,则可能是卖出信号。
操作示例:(仅作展示,具体可结合自己的系统以及品种具体分析)
1.买入交易设置
入场时机:等待价格反转并且砖块图形成三块蓝砖。然后确定第三块蓝砖的高点对应的价格,并在该价格水平设置买入止损单。同时,将止损设置在入场点后面三块砖的低点对应的价格。
退出时机:使用追踪止损,跟踪当前砖块图第三块砖的价格,允许价格在盈利时触及追踪止损。
2.卖出交易设置
入场时机:等待价格反转向下,并且砖块图形成三块红砖。然后确定第三块红砖的低点对应的价格,并在该价格水平设置卖出止损单。同时,将止损设置在入场点后面三块砖的高点对应的价格。
退出时机:使用追踪止损,跟踪当前砖块图第三块砖的价格,允许价格在盈利时触及追踪止损。
砖块图是一种非常有效的趋势和动量交易工具,但交易者需要适应它的工作方式。砖块图与蜡烛图不同,因此需要密切关注以判断动量是否发生逆转。如果您习惯长时间观察价格图表,砖块图将成为一个极好的工具,帮助抓住趋势和动量的逆转时机。
参数:
部分代码展示:
//+------------------------------------------------------------------+
//| 砖块图.mq4 |
//| Copyright © 2009-2024, www.QChaos.com |
//| https://www.qchaos.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 量化混沌, www.qchaos.com"
#property link "https://www.qchaos.com"
#property version "2.01"
//#property strict
#property indicator_separate_window
#property indicator_buffers 4
#property indicator_plots 4
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum BRICKSIZE
{
E=4, // AvgDailyRange,平均日幅度
F=5, // FixedPips,固定点数
};
bool CheckExpiry=false; // 检查是否过期
datetime dtExpiry=D'2088.12.31'; // 设置过期日期
bool CheckAccountNo=false; // 检查账户号
int iAccountNumber=123123; // 设置账户号
#property indicator_label2 "Lime" // 设置标签颜色
#property indicator_label3 "Red" // 设置标签颜色
//---- 输入参数
int Porog=200; // 门限值
extern BRICKSIZE 砖块类型=F; // 设置砖块尺寸类型
extern int 固定点数=200; // 固定点数
color ColorOfFon=clrBlack; // 背景颜色
color Color1=Lime; // 颜色1
color Color2=Red; // 颜色2
color SLcolor=LimeGreen; // 止损颜色
int SLstyle=STYLE_SOLID; // 止损样式
int SLwidth=2; // 止损线宽度
int RBstyle=STYLE_SOLID; // 砖块线样式
int RBwidth=1; // 砖块线宽度
color PJcolor=LimeGreen; // 投影颜色
int PJstyle=STYLE_DASH; // 投影样式
int PJwidth=1; // 投影线宽度
int RenkoWin=1; // 是否显示砖块图
int xDistance=5; // x轴距离
int yDistance=20; // y轴距离
bool DisplayHLine=false; // 是否显示水平线
//---- 缓存区
double Lab[]; // 存储砖块图的缓冲区
double HU[]; // 上行砖块的缓冲区
double HD[]; // 下行砖块的缓冲区
double Fon[]; // 背景的缓冲区
static int LastMinUpdate; // 上次更新时间
color RBcolor; // 砖块颜色
double Projection; // 投影值
// 新增的部分
int windowIndex; // 窗口索引
bool bError=false; // 错误标志
double dBSize; // 砖块尺寸
string strInd=MQLInfoString(MQL_PROGRAM_NAME),strFtc="Arial"; // 设置程序名和字体
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
strInd+="_"+IntegerToString(ChartWindowOnDropped());
IndicatorSetString(INDICATOR_SHORTNAME,strInd);
windowIndex=WindowFind(strInd);
if(CheckIniError())
return(INIT_FAILED);
dBSize=(砖块类型==E)?DayRange():固定点数;
IndicatorBuffers(4);
IndicatorShortName("砖块图("+dBSize+"pt)");
SetIndexStyle(0,DRAW_LINE,EMPTY,0,ColorOfFon);
SetIndexBuffer(0,Lab);
SetIndexLabel(0,"砖块图");
SetIndexEmptyValue(0,0);
SetIndexStyle(1,DRAW_HISTOGRAM,EMPTY,8,Color1);
SetIndexBuffer(1,HU);
SetIndexEmptyValue(1,0);
SetIndexStyle(2,DRAW_HISTOGRAM,EMPTY,8,Color2);
SetIndexBuffer(2,HD);
SetIndexEmptyValue(2,0);
SetIndexStyle(3,DRAW_HISTOGRAM,EMPTY,8,ColorOfFon);
SetIndexBuffer(3,Fon);
SetIndexLabel(3,NULL);
SetIndexEmptyValue(3,0);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
for(int ii=ObjectsTotal(); ii>=0; ii--)
{ if(StringFind(ObjectName(ii),strInd,0)!=-1) ObjectDelete(ObjectName(ii)); }
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
if(bError)
return(-1);
int i,RenkoBuffShift=0;
double RenkoBuff[];
double RenkoBuff2[];
dBSize=(砖块类型==E)?DayRange():固定点数;
IndicatorSetString(INDICATOR_SHORTNAME,"砖块图("+dBSize+"pt)");
double StopLoss;
string ObjectStringSL,ObjectStringRB,ObjectStringPJ,ObjectStringText;
ObjectStringSL=strInd+"StopLoss" + dBSize;
ObjectStringRB=strInd+"RenkoBlock" + dBSize;
ObjectStringPJ=strInd+"Projection" + dBSize;
ObjectStringText=strInd+"Text"+dBSize;
ArrayResize(RenkoBuff,Bars);
ArrayResize(RenkoBuff2,Bars);
RenkoBuff[RenkoBuffShift]=Close[Bars-1];
for(i=Bars-2; i>0; i--)
{
if(RenkoBuffShift>ArraySize(RenkoBuff)-100)
{
ArrayCopy(RenkoBuff2,RenkoBuff);
ArrayResize(RenkoBuff,ArraySize(RenkoBuff)+Bars);
ArrayCopy(RenkoBuff,RenkoBuff2,0,0,RenkoBuffShift+1);
ArrayResize(RenkoBuff2,ArraySize(RenkoBuff2)+Bars);
}
if(RenkoBuffShift==0)
{
while(Close[i]>RenkoBuff[RenkoBuffShift]+dBSize*Point &&
RenkoBuffShift<ArraySize(RenkoBuff))
{
RenkoBuffShift++;
RenkoBuff[RenkoBuffShift]=RenkoBuff[RenkoBuffShift-1]+dBSize*Point;
}
while(Close[i]<RenkoBuff[RenkoBuffShift]-dBSize*Point &&
RenkoBuffShift<ArraySize(RenkoBuff))
{
RenkoBuffShift++;
RenkoBuff[RenkoBuffShift]=RenkoBuff[RenkoBuffShift-1]-dBSize*Point;
}
}
if(RenkoBuff[RenkoBuffShift]>RenkoBuff[RenkoBuffShift-1])
{
if(Close[i]>RenkoBuff[RenkoBuffShift]+dBSize*Point)
{
while(Close[i]>RenkoBuff[RenkoBuffShift]+dBSize*Point &&
RenkoBuffShift<ArraySize(RenkoBuff))
{
RenkoBuffShift++;
RenkoBuff[RenkoBuffShift]=RenkoBuff[RenkoBuffShift-1]+dBSize*Point;
}
}
if(Close[i]<RenkoBuff[RenkoBuffShift]-2*dBSize*Point)
{
RenkoBuffShift++;
RenkoBuff[RenkoBuffShift]=RenkoBuff[RenkoBuffShift-1]-2*dBSize*Point;
while(Close[i]<RenkoBuff[RenkoBuffShift]-dBSize*Point &&
RenkoBuffShift<ArraySize(RenkoBuff))
{
RenkoBuffShift++;
RenkoBuff[RenkoBuffShift]=RenkoBuff[RenkoBuffShift-1]-dBSize*Point;
}
}
}
if(RenkoBuff[RenkoBuffShift]<RenkoBuff[RenkoBuffShift-1])
{
if(Close[i]<RenkoBuff[RenkoBuffShift]-dBSize*Point)
{
while(Close[i]<RenkoBuff[RenkoBuffShift]-dBSize*Point &&
RenkoBuffShift<ArraySize(RenkoBuff))
{
RenkoBuffShift++;
RenkoBuff[RenkoBuffShift]=RenkoBuff[RenkoBuffShift-1]-dBSize*Point;
}
}
if(Close[i]>RenkoBuff[RenkoBuffShift]+2*dBSize*Point)
{
RenkoBuffShift++;
RenkoBuff[RenkoBuffShift]=RenkoBuff[RenkoBuffShift-1]+2*dBSize*Point;
while(Close[i]>RenkoBuff[RenkoBuffShift]+dBSize*Point &&
RenkoBuffShift<ArraySize(RenkoBuff))
{
RenkoBuffShift++;
RenkoBuff[RenkoBuffShift]=RenkoBuff[RenkoBuffShift-1]+dBSize*Point;
}
}
}
}
///
for(i=0; i<Bars; i++)
{
Lab[i]=0;
HU[i]=0;
HD[i]=0;
Fon[i]=0;
}
if(RenkoBuffShift>Bars-100)
{
for(i=0; i<=Bars-100 && i<ArraySize(RenkoBuff); i++)
RenkoBuff[i]=RenkoBuff[i+RenkoBuffShift-(Bars-100)];
RenkoBuffShift=Bars-100;
}
for(i=1; i<=RenkoBuffShift && i<ArraySize(Lab); i++)
Lab[RenkoBuffShift-i]=RenkoBuff[i];
for(i=1; i<=RenkoBuffShift && i<ArraySize(RenkoBuff) &&
RenkoBuffShift-i<ArraySize(HU) && RenkoBuffShift-i<ArraySize(HD) &&
RenkoBuffShift-i<ArraySize(Fon); i++)
{
if(RenkoBuff[i]>RenkoBuff[i-1] && RenkoBuff[i-1]>RenkoBuff[i-2])
{
HU[RenkoBuffShift-i]=RenkoBuff[i];
HD[RenkoBuffShift-i]=RenkoBuff[i-1];
Fon[RenkoBuffShift-i]=RenkoBuff[i-1];
}
if(RenkoBuff[i]>RenkoBuff[i-1] && RenkoBuff[i-1]<RenkoBuff[i-2])
{
HU[RenkoBuffShift-i]=RenkoBuff[i];
HD[RenkoBuffShift-i]=RenkoBuff[i]-dBSize*Point;
Fon[RenkoBuffShift-i]=RenkoBuff[i]-dBSize*Point;
}
if(RenkoBuff[i]<RenkoBuff[i-1] && RenkoBuff[i-1]<RenkoBuff[i-2])
{
HD[RenkoBuffShift-i]=RenkoBuff[i-1];
HU[RenkoBuffShift-i]=RenkoBuff[i];
Fon[RenkoBuffShift-i]=RenkoBuff[i];
}
if(RenkoBuff[i]<RenkoBuff[i-1] && RenkoBuff[i-1]>RenkoBuff[i-2])
{
HD[RenkoBuffShift-i]=RenkoBuff[i]+dBSize*Point;
HU[RenkoBuffShift-i]=RenkoBuff[i];
Fon[RenkoBuffShift-i]=RenkoBuff[i];
}
}
///
if(DisplayHLine && LastMinUpdate!=TimeMinute(TimeCurrent()))
{
if(HD[0]==Fon[0])
{
StopLoss=HU[0]-2*dBSize*Point;
RBcolor=Color1;
Projection=HU[0]+dBSize*Point;
}
else
{
StopLoss=HU[0]+2*dBSize*Point;
RBcolor=Color2;
Projection=HU[0]-dBSize*Point;
}
if(ObjectFind(ObjectStringSL)!=-1)
ObjectDelete(ObjectStringSL);
if(ObjectFind(ObjectStringRB)!=-1)
ObjectDelete(ObjectStringRB);
if(ObjectFind(ObjectStringPJ)!=-1)
ObjectDelete(ObjectStringPJ);
if(ObjectFind(ObjectStringText)!=-1)
ObjectDelete(ObjectStringText);
ObjectCreate(ObjectStringSL,OBJ_HLINE,0,Time[5],StopLoss);
ObjectSet(ObjectStringSL,OBJPROP_COLOR,SLcolor);
ObjectSet(ObjectStringSL,OBJPROP_STYLE,SLstyle);
ObjectSet(ObjectStringSL,OBJPROP_WIDTH,SLwidth);
ObjectCreate(ObjectStringPJ,OBJ_HLINE,0,Time[5],Projection);
ObjectSet(ObjectStringPJ,OBJPROP_COLOR,PJcolor);
ObjectSet(ObjectStringPJ,OBJPROP_STYLE,PJstyle);
ObjectSet(ObjectStringPJ,OBJPROP_WIDTH,PJwidth);
LastMinUpdate=TimeMinute(TimeCurrent());
}
return(rates_total);
}
//+------------------------------------------------------------------+
double DayRange(bool ai_0=TRUE)
{
double ld_4=iHigh(NULL,PERIOD_D1,1)-iLow(NULL,PERIOD_D1,1);
double ld_12=ld_4+iHigh(NULL,PERIOD_D1,2)-iLow(NULL,PERIOD_D1,2);
ld_12 += iHigh(NULL, PERIOD_D1, 3) - iLow(NULL, PERIOD_D1, 3);
ld_12 += iHigh(NULL, PERIOD_D1, 4) - iLow(NULL, PERIOD_D1, 4);
ld_12 += iHigh(NULL, PERIOD_D1, 5) - iLow(NULL, PERIOD_D1, 5);
double ld_20=ld_12+iHigh(NULL,PERIOD_D1,6)-iLow(NULL,PERIOD_D1,6);
ld_20 += iHigh(NULL, PERIOD_D1, 7) - iLow(NULL, PERIOD_D1, 7);
ld_20 += iHigh(NULL, PERIOD_D1, 8) - iLow(NULL, PERIOD_D1, 8);
ld_20 += iHigh(NULL, PERIOD_D1, 9) - iLow(NULL, PERIOD_D1, 9);
ld_20 += iHigh(NULL, PERIOD_D1, 10) - iLow(NULL, PERIOD_D1, 10);
double ld_28=ld_20+iHigh(NULL,PERIOD_D1,11)-iLow(NULL,PERIOD_D1,11);
ld_28 += iHigh(NULL, PERIOD_D1, 12) - iLow(NULL, PERIOD_D1, 12);
ld_28 += iHigh(NULL, PERIOD_D1, 13) - iLow(NULL, PERIOD_D1, 13);
ld_28 += iHigh(NULL, PERIOD_D1, 14) - iLow(NULL, PERIOD_D1, 14);
ld_28 += iHigh(NULL, PERIOD_D1, 15) - iLow(NULL, PERIOD_D1, 15);
ld_28 += iHigh(NULL, PERIOD_D1, 16) - iLow(NULL, PERIOD_D1, 16);
ld_28 += iHigh(NULL, PERIOD_D1, 17) - iLow(NULL, PERIOD_D1, 17);
ld_28 += iHigh(NULL, PERIOD_D1, 18) - iLow(NULL, PERIOD_D1, 18);
ld_28 += iHigh(NULL, PERIOD_D1, 19) - iLow(NULL, PERIOD_D1, 19);
ld_28 += iHigh(NULL, PERIOD_D1, 20) - iLow(NULL, PERIOD_D1, 20);
ld_12 = 0.2 * ld_12;
ld_20/= 10.0;
ld_28 = 0.05 * ld_28;
if(ai_0)
return ((ld_4 + ld_12 + ld_20 + ld_28) / 4.0 / Point);
return ((ld_4 + ld_12 + ld_20 + ld_28) / 8.0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CheckIniError()
{
if(CheckExpiry)
{
if(TimeCurrent()>(dtExpiry+24*3600-1))
{
SetLabel(strInd+"_ERROR",windowIndex,"Expired...",10,20,strFtc,12,Red);
bError=true;
return(true);
}
else
SetLabel(strInd+"_ERROR",windowIndex,"Valid by "+TimeToString(dtExpiry,TIME_DATE),5,5,strFtc,9,Aqua,
CORNER_LEFT_LOWER,ANCHOR_LEFT_LOWER);
}
if(CheckAccountNo && AccountNumber()!=iAccountNumber && !IsDemo())
{
SetLabel(strInd+"_ERROR",windowIndex,"Invalid user account...",5,20,strFtc,12,Red);
bError=true;
return(true);
}
bError=false;
return(false);
}