费了好大神才找到出处。
用于上涨、下跌确认,紧跟3号球之后,
原文件是LabTrend1_V2.mq4,还有一个V2.1未研究。
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_color1 Blue
#property indicator_color2 Red
#property indicator_color3 Blue
#property indicator_color4 Red
extern double 收缩系数 = 3.0; //价格通道收缩系数1~10
extern int 时框 = 0; //单位:分钟
extern int Signal = 1; //显示信号
extern int ColorBar = 3; //显示bar的颜色,0-no,1-yes
extern int 发声 = 0;
double 上涨趋势信号[];
double 下跌趋势信号[];
double 上涨柱[];
double 下跌柱[];
double smax[]; //数组极高
double smin[];
double 趋势[];
int 开始处 = 9;
int 现时[2];
bool 智能程序 = TRUE;
double BSMAX[2];
double BSMIN[2];
bool 已报涨 = FALSE;
bool 已报跌 = FALSE;
int init()
{
IndicatorBuffers(7);
SetIndexBuffer(0, 上涨趋势信号); //blue 实心球
SetIndexBuffer(1, 下跌趋势信号); //red 实心球
SetIndexBuffer(2, 上涨柱); //blue 背景
SetIndexBuffer(3, 下跌柱); //red 背景
SetIndexBuffer(4, smax);
SetIndexBuffer(5, smin);
SetIndexBuffer(6, 趋势);
SetIndexStyle(0, DRAW_ARROW,0,1);
SetIndexStyle(1, DRAW_ARROW,0,1);
SetIndexStyle(2, DRAW_HISTOGRAM,0,1);
SetIndexStyle(3, DRAW_HISTOGRAM,0,1);
SetIndexArrow(0, 108);//实心球
SetIndexArrow(1, 108);
string 标签 = "SS2009_A(" + DoubleToStr(收缩系数, 2) + ")";
IndicatorShortName(标签);
SetIndexLabel(0, "上涨趋势信号");
SetIndexLabel(1, "下降趋势信号");
SetIndexLabel(2, "上涨bar");
SetIndexLabel(3, "下降bar");
SetIndexEmptyValue(0, 0.0);
SetIndexEmptyValue(1, 0.0);
SetIndexEmptyValue(2, 0.0);
SetIndexEmptyValue(3, 0.0);
SetIndexDrawBegin(0, 开始处);//划线开始点
SetIndexDrawBegin(1, 开始处);
SetIndexDrawBegin(2, 开始处);
SetIndexDrawBegin(3, 开始处);
return (0);
}
int start()
{
int 开盘时间数组[];
double UpBar; //开始涨了时候的值
double DnBar;
double 上限[1]; //极值
double 下限[1];
double 最低价数组[];
double 最高价数组[];
string 内容;
int j = 0;
int 已计 = IndicatorCounted(); //已经计算过的有值的柱数,假设998
/*
指标刚加载到图上的时候,IndicatorCounted()=0,
然后程序会自动计算一遍所有K线对应的指标数值并画线。
然后每来一个tick的时候,Bars减去IndicatorCounted()后就只剩下1或者2了(视指标的计算方式决定)。
这时候for循环只需要计算这些有变动的K线对应的指标数值就行了,不需要从头到尾重复计算了,提高效率。
*/
if (Bars - 1 < 开始处 + 1) return (0);
//开始处=9,本EA起作用需要从右到左第10根开始,Bars-1表示从右到左0..Bars-1共Bars根K线
//假设Bars=5,还不够计算指标的,刚装的MT4吧?
if (已计 < 0) return (-1); //系统乱了
if (已计 > 0) 已计--; //自减一操作997
//从已经计算的指标中去除最后一条。
//这条语句用来修正counted_bars使得已经计算的最后一个数值可以在接下来的运算中重新计算一次,这样好衔接起来呀。
//主函数每次tick都会运行一次,当运行完成后,IndicatorCounted()等于Bars,也就是K线根数
//如果无自减一操作,那么当价格变动有了新的收盘价但没生成新K线,此时limit=0,那么后面的for循环将不会计算最后一根K线对应的指标数值
int 最多柱数 = Bars - 1 - 开始处 - 1; //假设Bars=1000,那么最多柱数=1000-11=989
int 未计 = Bars - 已计 - 1 + 时框/Period(); //时框=0, 未计=1000-998-1+时框=1+时框
if (未计 > 最多柱数) //1+时框>989...看来没法成立
{
for (int i = 未计; i >= 最多柱数; i--) //未计的初始化,一直减到未计等于最多柱数为止
{
smax[Bars - i] = 0.0;
smin[Bars - i] = 0.0;
上涨趋势信号[Bars - i] = 0.0;
下跌趋势信号[Bars - i] = 0.0;
上涨柱[Bars - i] = 0.0;
下跌柱[Bars - i] = 0.0;
}
未计 = 最多柱数;
}
if (ArrayResize(下限, 未计 + 2) != 未计 + 2) return (-1);//3个元素而已
if (ArrayResize(上限, 未计 + 2) != 未计 + 2) return (-1);
int 新时刻 = Time[未计 + 1]; //Time[2],从右到左第三根的开盘时间,很大的秒数
if (未计 < 最多柱数) //正常情况下成立
{
if (新时刻 == 现时[1]) //新时刻等于从右到左第二根的开盘时间,过去一根K的时间与新时刻比较
{
下限[未计 + 1] = BSMIN[1];//下限[2]=BSMIN[1]
上限[未计 + 1] = BSMAX[1];
智能程序 = FALSE; //已完成前移操作,故后面不需要重复操作了。
}
else
{
if (新时刻 == 现时[0]) //当前时刻
{
下限[未计 + 1] = BSMIN[0];//下限[2]=BSMIN[0]
上限[未计 + 1] = BSMAX[0];
BSMIN[1] = BSMIN[0]; //移位,新值取代旧值
BSMAX[1] = BSMAX[0];
}
else
{
if (新时刻 > 现时[1]) Print("错误1");
else Print("错误2"); //大于是错,不大于也是错,必须等于
return (-1);
}
}
}
ArrayCopySeries(开盘时间数组, 5, Symbol(), 时框); //5-Mode_TIME-Bar开盘时间,时框=0,即当前时框
ArrayCopySeries(最低价数组, 1, Symbol(), 时框); //1-Mode_LOW-最低价
ArrayCopySeries(最高价数组, 2, Symbol(), 时框); //2-Mode_HIGH-最高价
//找数组中的极值
i = 0;
for (j = 0; i < 未计; i++) //i=0..1
{
if (Time[i] < 开盘时间数组[j]) j++;
//当i=0时,如果j=0,则有可能相等,if不满足
//若不相等或<,说明Time[0]是新的,开盘时间数组[0]过时了,j退回到上一根K线
//当i=1时,如果j=0,if条件满足,j退回;
//当i=1时,如果j=1,if条件还是<成立,则说明Time[1]比开盘时间数组[1]新,j退回;
//由上,j=0..2
smin[i] = 10000000; //极值归位
smax[i] = -100000000;
for (int k = 开始处 - 1; k >= 0; k--) //赋值,K=8..0
{
smin[i] = MathMin(smin[i], 最低价数组[j + k]);
//两者之间找小的,当然把最低价[j+k]赋值给smin[i]咯
smax[i] = MathMax(smax[i], 最高价数组[j + k]);
}
}
for (i = 未计; i >= 0; i--) //i=1..0
{
上涨趋势信号[i] = 0.0;
下跌趋势信号[i] = 0.0;
上涨柱[i] = 0.0;
下跌柱[i] = 0.0;
//计算通道阈值,±30%赋值给上限和下限
上限[i] = smax[i] - (smax[i] - smin[i]) * (33.0 - 收缩系数) / 100.0;
下限[i] = smin[i] + (smax[i] - smin[i]) * (33.0 - 收缩系数) / 100.0;
//价格突破
趋势[i] = 趋势[i + 1];
//趋势[1]=趋势[2],然后趋势[0]=趋势[1],移位
if (趋势[i + 1] < 0.0 && Close[i] > 上限[i]) 趋势[i] = 1;
if (趋势[i + 1] > 0.0 && Close[i] < 下限[i]) 趋势[i] = -1;
//绘图
UpBar = 上限[i]; //赋值
DnBar = 下限[i];
if (趋势[i] > 0.0) //涨势
{
if (Signal > 0 && 趋势[i + 1] < 0.0) //Signal=1
{
上涨趋势信号[i] = Low[i] - iATR(NULL, 时框, 10, i) / 2.0;
//上涨趋势信号放在当前最低值-ATR之下
if (发声 > 0 && i == 0) PlaySound("alert2.wav");
}
else 上涨趋势信号[i] = EMPTY_VALUE;//在底部显示
if (ColorBar > 0) //K线背景颜色
{
if (Close[i] > UpBar) //上限
{
上涨柱[i] = High[i];
下跌柱[i] = Low[i];
}
else
{
上涨柱[i] = 0.0;
下跌柱[i] = 0.0;
}
}
}
else //跌势
{
if (趋势[i] < 0.0)
{
if (Signal == 1 && 趋势[i + 1] > 0.0)
{
下跌趋势信号[i] = High[i] + iATR(NULL, 时框, 10, i) / 2.0;
//下跌趋势信号放在当前最高值+ATR之上
if (发声 > 0 && i == 0) PlaySound("alert2.wav");
}
else 下跌趋势信号[i] = 0.0;//不设置EMPTY_VALUE,否则底部交替信号,眼花缭乱
if (ColorBar > 0)
{
if (Close[i] < DnBar) //下限
{
上涨柱[i] = Low[i];
下跌柱[i] = High[i];
}
else
{
上涨柱[i] = 0.0;
下跌柱[i] = 0.0;
}
}
}
}
//
if (i == 2 || (i == 1 && 智能程序 == TRUE))
{
现时[i - 1] = Time[i];//只有这里,将Time[0]或Time[1]赋值给现时
BSMIN[i - 1] = 下限[i];
BSMAX[i - 1] = 上限[i];
//如果i=2,则平移数组,相当于衔接工作
//如果i=1,看有没有上面 过去时刻 的情况
}
}
if (趋势[2] < 0.0 && 趋势[1] > 0.0 && Volume[0] > 1 && !已报涨)
{
内容 = "币"+Symbol()+"在时框M"+Period()+"下的信号为BUY";
if (发声 > 0 && NewBar() == 1) Alert(内容);
已报涨 = TRUE;
已报跌 = FALSE;
}
if (趋势[2] > 0.0 && 趋势[1] < 0.0 && Volume[0] > 1 && !已报跌)
{
内容 = "币"+Symbol()+"在时框M"+Period()+"下的信号为SELL";
if (发声 > 0 && NewBar() == 1) Alert(内容);
已报跌 = TRUE;
已报涨 = FALSE;
}
return (0);
}
int NewBar() //检测来的新柱,否则start函数被每一个tick触发
{
static datetime 前柱;
datetime 现柱 = Time[0];
if (前柱 != 现柱)
{
前柱 = 现柱;
return (1);
}
else return (0);
发表评论