您好、
我添加了相对时间框架......这是从 Nikolay Kositin 那里得到的想法、
例如
(实际)第一时间框架
(实际+1)第二个时间框架
(actual+2) 第三个时间框架
等...
//+------------------------------------------------------------------+ //|SVSI_MTF.mq5 | | //| Copyright 2018, MetaQuotes Software Corp. //|https://mql5.com //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://mql5.com" #property version "1.01" #property description "Multi timeframe Slow Volume Strength Index oscillator" #property indicator_separate_window #property indicator_buffers 15 #property indicator_plots 3 //--- 绘制 SVSI 1 #property indicator_label1 "SVSI 1" #property indicator_type1 DRAW_LINE #property indicator_color1 clrRed #property indicator_style1 STYLE_SOLID #property indicator_width1 2 //--- 绘制 SVSI 2 #property indicator_label2 "SVSI 2" #property indicator_type2 DRAW_LINE #property indicator_color2 clrGreen #property indicator_style2 STYLE_SOLID #property indicator_width2 2 //--- 绘制 SVSI 3 #property indicator_label3 "SVSI 3" #property indicator_type3 DRAW_LINE #property indicator_color3 clrBlue #property indicator_style3 STYLE_SOLID #property indicator_width3 2 //-- 枚举 enum ENUM_DRAW_MODE { DRAW_MODE_STEPS, // 步骤。 DRAW_MODE_SLOPE // 斜坡 }; //--- // enum enTimeFrames { tf_cu = PERIOD_CURRENT, // 当前时间框架 tf_m1 = PERIOD_M1, // 1 分钟 tf_m2 = PERIOD_M2, // 2 分钟 tf_m3 = PERIOD_M3, // 3 分钟 tf_m4 = PERIOD_M4, // 4 分钟 tf_m5 = PERIOD_M5, // 5 分钟 tf_m6 = PERIOD_M6, // 6 分钟 tf_m10 = PERIOD_M10, // 10 分钟 tf_m12 = PERIOD_M12, // 12 分钟 tf_m15 = PERIOD_M15, // 15 分钟 tf_m20 = PERIOD_M20, // 20 分钟 tf_m30 = PERIOD_M30, // 30 分钟 tf_h1 = PERIOD_H1, // 1 小时 tf_h2 = PERIOD_H2, // 2 小时 tf_h3 = PERIOD_H3, // 3 小时 tf_h4 = PERIOD_H4, // 4 小时 tf_h6 = PERIOD_H6, // 6 小时 tf_h8 = PERIOD_H8, // 8 小时 tf_h12 = PERIOD_H12, // 12 小时 tf_d1 = PERIOD_D1, // 每天 tf_w1 = PERIOD_W1, // 每周 tf_mn = PERIOD_MN1, // 每月 tf_cp1 = -1, // 下一个更高的时间段 tf_cp2 = -2, // 第二个更高的时间框架 tf_cp3 = -3, // 第三个更高的时间框架 tf_cp4 = -4, // 第四个更高的时间框架 tf_cp5 = -5, // 第五个更高的时间框架 tf_cp6 = -6 // 第六个更高的时间框架 }; ENUM_TIMEFRAMES _tfsPer[]={PERIOD_M1,PERIOD_M2,PERIOD_M3,PERIOD_M4,PERIOD_M5,PERIOD_M6,PERIOD_M10,PERIOD_M12,PERIOD_M15,PERIOD_M20,PERIOD_M30,PERIOD_H1,PERIOD_H2,PERIOD_H3,PERIOD_H4,PERIOD_H6,PERIOD_H8,PERIOD_H12,PERIOD_D1,PERIOD_W1,PERIOD_MN1}; // //--- // //--- 输入参数 input uint InpPeriodMA = 6; // EMA 周期。 input uint InpPeriodSm = 14; // 平滑 input double InpOverbought = 80.0; // 超买 input double InpMiddle = 50.0; // 中间 input double InpOversold = 20.0; // 超卖 input ENUM_DRAW_MODE InpDrawMode = DRAW_MODE_STEPS; // 绘图模式 input enTimeFrames InpTimeframe1 = PERIOD_CURRENT; // 第一个 SVSI 时间框架 input enTimeFrames InpTimeframe2 = tf_cp1; // 第二个 SVSI 时间框架 input enTimeFrames InpTimeframe3 = tf_cp2; // 第二个 SVSI 时间框架 //--- 指示器缓冲区 double BufferSVSI1[]; double BufferSVSI2[]; double BufferSVSI3[]; double BufferSVSI1tmp[]; double BufferSVSI2tmp[]; double BufferSVSI3tmp[]; double BufferPos1[]; double BufferNeg1[]; double BufferMA1[]; double BufferPos2[]; double BufferNeg2[]; double BufferMA2[]; double BufferPos3[]; double BufferNeg3[]; double BufferMA3[]; //--- 全局变量 ENUM_TIMEFRAMES timeframe1; ENUM_TIMEFRAMES timeframe2; ENUM_TIMEFRAMES timeframe3; double overbought; double middle; double oversold; int period_ma; int period_sm; int handle_ma1; int handle_ma2; int handle_ma3; ENUM_TIMEFRAMES ExtTimeFrame1; ENUM_TIMEFRAMES ExtTimeFrame2; ENUM_TIMEFRAMES ExtTimeFrame3; //+------------------------------------------------------------------+ //| 自定义指示器初始化函数 //+------------------------------------------------------------------+ int OnInit() { //--计算指标时间框架 ExtTimeFrame1 = MathMax(timeFrameGet((int)InpTimeframe1),_Period); ExtTimeFrame2 = MathMax(timeFrameGet((int)InpTimeframe2),_Period); ExtTimeFrame3 = MathMax(timeFrameGet((int)InpTimeframe3),_Period); //--- 计时器 EventSetTimer(90); //--- 设置全局变量 period_ma=int(InpPeriodMA<1 ? 1 : InpPeriodMA); period_sm=int(InpPeriodSm<1 ? 1 : InpPeriodSm); timeframe1=(ExtTimeFrame1>Period() ? ExtTimeFrame1 : Period()); timeframe2=(ExtTimeFrame2>Period() ? ExtTimeFrame2 : Period()); timeframe3=(ExtTimeFrame3>Period() ? ExtTimeFrame3 : Period()); middle=(InpMiddle>99.9 ? 99.9 : InpMiddle<0.1 ? 0.1 : InpMiddle); overbought=(InpOverbought>100 ? 100 : InpOverbought<=middle ? middle+0.1 : InpOverbought); oversold=(InpOversold<0 ? 0 : InpOversold>=middle ? middle-0.1 : InpOversold); //--- 指示器缓冲区映射 SetIndexBuffer(0,BufferSVSI1,INDICATOR_DATA); SetIndexBuffer(1,BufferSVSI2,INDICATOR_DATA); SetIndexBuffer(2,BufferSVSI3,INDICATOR_DATA); SetIndexBuffer(3,BufferSVSI1tmp,INDICATOR_CALCULATIONS); SetIndexBuffer(4,BufferSVSI2tmp,INDICATOR_CALCULATIONS); SetIndexBuffer(5,BufferSVSI3tmp,INDICATOR_CALCULATIONS); SetIndexBuffer(6,BufferPos1,INDICATOR_CALCULATIONS); SetIndexBuffer(7,BufferNeg1,INDICATOR_CALCULATIONS); SetIndexBuffer(8,BufferMA1,INDICATOR_CALCULATIONS); SetIndexBuffer(9,BufferPos2,INDICATOR_CALCULATIONS); SetIndexBuffer(10,BufferNeg2,INDICATOR_CALCULATIONS); SetIndexBuffer(11,BufferMA2,INDICATOR_CALCULATIONS); SetIndexBuffer(12,BufferPos3,INDICATOR_CALCULATIONS); SetIndexBuffer(13,BufferNeg3,INDICATOR_CALCULATIONS); SetIndexBuffer(14,BufferMA3,INDICATOR_CALCULATIONS); //--- 设置指示器参数 string label=TimeframeToString(timeframe1)+","+TimeframeToString(timeframe2)+","+TimeframeToString(timeframe3)+" SVSI("+(string)period_ma+","+(string)period_sm+")"; IndicatorSetString(INDICATOR_SHORTNAME,label); IndicatorSetInteger(INDICATOR_DIGITS,Digits()); IndicatorSetInteger(INDICATOR_LEVELS,3); IndicatorSetDouble(INDICATOR_LEVELVALUE,0,overbought); IndicatorSetDouble(INDICATOR_LEVELVALUE,1,middle); IndicatorSetDouble(INDICATOR_LEVELVALUE,2,oversold); IndicatorSetString(INDICATOR_LEVELTEXT,0,"Overbought"); IndicatorSetString(INDICATOR_LEVELTEXT,2,"Oversold"); IndicatorSetInteger(INDICATOR_LEVELCOLOR,0,clrSlateGray); IndicatorSetInteger(INDICATOR_LEVELCOLOR,1,clrSlateGray); IndicatorSetInteger(INDICATOR_LEVELCOLOR,2,clrSlateGray); //--- 设置绘图缓冲区参数 PlotIndexSetString(0,PLOT_LABEL,TimeframeToString(timeframe1)+" SVSI("+(string)period_ma+","+(string)period_sm+")"); PlotIndexSetString(1,PLOT_LABEL,TimeframeToString(timeframe2)+" SVSI("+(string)period_ma+","+(string)period_sm+")"); PlotIndexSetString(2,PLOT_LABEL,TimeframeToString(timeframe3)+" SVSI("+(string)period_ma+","+(string)period_sm+")"); //--- 将缓冲数组设置为时间序列 ArraySetAsSeries(BufferSVSI1,true); ArraySetAsSeries(BufferSVSI2,true); ArraySetAsSeries(BufferSVSI3,true); ArraySetAsSeries(BufferSVSI1tmp,true); ArraySetAsSeries(BufferSVSI2tmp,true); ArraySetAsSeries(BufferSVSI3tmp,true); ArraySetAsSeries(BufferPos1,true); ArraySetAsSeries(BufferNeg1,true); ArraySetAsSeries(BufferMA1,true); ArraySetAsSeries(BufferPos2,true); ArraySetAsSeries(BufferNeg2,true); ArraySetAsSeries(BufferMA2,true); ArraySetAsSeries(BufferPos3,true); ArraySetAsSeries(BufferNeg3,true); ArraySetAsSeries(BufferMA3,true); //--- 创建句柄 ResetLastError(); handle_ma1=iMA(NULL,timeframe1,period_ma,0,MODE_EMA,PRICE_CLOSE); if(handle_ma1==INVALID_HANDLE) { Print(__LINE__,": The iMA(",(string)period_ma,") object was not created: Error ",GetLastError()); return INIT_FAILED; } handle_ma2=iMA(NULL,timeframe2,period_ma,0,MODE_EMA,PRICE_CLOSE); if(handle_ma2==INVALID_HANDLE) { Print(__LINE__,": The iMA(",(string)period_ma,") object was not created: Error ",GetLastError()); return INIT_FAILED; } handle_ma3=iMA(NULL,timeframe3,period_ma,0,MODE_EMA,PRICE_CLOSE); if(handle_ma3==INVALID_HANDLE) { Print(__LINE__,": The iMA(",(string)period_ma,") object was not created: Error ",GetLastError()); return INIT_FAILED; } //--- 获取时间框架 Time(NULL,timeframe1,1); Time(NULL,timeframe2,1); Time(NULL,timeframe3,1); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| 自定义指标迭代函数 //+------------------------------------------------------------------+ 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(rates_total<fmax(period_sm,4)) return 0; //--- 检查并计算要计算的条数 int limit=rates_total-prev_calculated; if(limit>1) { limit=rates_total-period_sm-1; ArrayInitialize(BufferSVSI1,EMPTY_VALUE); ArrayInitialize(BufferSVSI2,EMPTY_VALUE); ArrayInitialize(BufferSVSI3,EMPTY_VALUE); ArrayInitialize(BufferSVSI1tmp,0); ArrayInitialize(BufferSVSI2tmp,0); ArrayInitialize(BufferSVSI3tmp,0); ArrayInitialize(BufferPos1,0); ArrayInitialize(BufferNeg1,0); ArrayInitialize(BufferMA1,0); ArrayInitialize(BufferPos2,0); ArrayInitialize(BufferNeg2,0); ArrayInitialize(BufferMA2,0); ArrayInitialize(BufferPos3,0); ArrayInitialize(BufferNeg3,0); ArrayInitialize(BufferMA3,0); } //--- 数据准备 if(Time(NULL,timeframe1,1)==0 || Time(NULL,timeframe2,1)==0 || Time(NULL,timeframe3,1)==0) return 0; int bars1=(timeframe1==Period() ? rates_total : Bars(NULL,timeframe1)); int bars2=(timeframe2==Period() ? rates_total : Bars(NULL,timeframe2)); int bars3=(timeframe3==Period() ? rates_total : Bars(NULL,timeframe3)); int count1=(limit>1 ? fmin(bars1,rates_total) : 1); int copied1=CopyBuffer(handle_ma1,0,0,count1,BufferMA1); if(copied1!=count1) return 0; int count2=(limit>1 ? fmin(bars2,rates_total) : 1); int copied2=CopyBuffer(handle_ma2,0,0,count2,BufferMA2); if(copied2!=count2) return 0; int count3=(limit>1 ? fmin(bars3,rates_total) : 1); int copied3=CopyBuffer(handle_ma3,0,0,count3,BufferMA3); if(copied3!=count3) return 0; for(int i=limit; i>=0 && !IsStopped(); i--) { if(!DataPreparing(i,timeframe1,BufferMA1,BufferPos1,BufferNeg1)) continue; if(!DataPreparing(i,timeframe2,BufferMA2,BufferPos2,BufferNeg2)) continue; if(!DataPreparing(i,timeframe3,BufferMA3,BufferPos3,BufferNeg3)) continue; } for(int i=limit; i>=0 && !IsStopped(); i--) { SVSI(rates_total,i,period_sm,BufferPos1,BufferNeg1,BufferSVSI1tmp); SVSI(rates_total,i,period_sm,BufferPos2,BufferNeg2,BufferSVSI2tmp); SVSI(rates_total,i,period_sm,BufferPos3,BufferNeg3,BufferSVSI3tmp); } //--- 计算指标 for(int i=limit; i>=0 && !IsStopped(); i--) { DataConversion(rates_total,NULL,timeframe1,i,BufferSVSI1tmp,BufferSVSI1,InpDrawMode); DataConversion(rates_total,NULL,timeframe2,i,BufferSVSI2tmp,BufferSVSI2,InpDrawMode); DataConversion(rates_total,NULL,timeframe3,i,BufferSVSI3tmp,BufferSVSI3,InpDrawMode); } //--- 为下一次调用返回 prev_calculated 的值 return(rates_total); } //+------------------------------------------------------------------+ //| 自定义指示计时器功能| //+------------------------------------------------------------------+ void OnTimer() { Time(NULL,timeframe1,1); Time(NULL,timeframe2,1); Time(NULL,timeframe3,1); } //+------------------------------------------------------------------+ // 从源时间框架向当前时间框架传输数据 //+------------------------------------------------------------------+ void DataConversion(const int rates_total, const string symbol_name, const ENUM_TIMEFRAMES timeframe_src, const int shift, const double &buffer_src[], double &buffer_dest[], ENUM_DRAW_MODE mode=DRAW_MODE_STEPS ) { if(timeframe_src==Period()) { buffer_dest[shift]=buffer_src[shift]; return; } int bar_curr=BarToCurrent(symbol_name,timeframe_src,shift); if(bar_curr>rates_total-1) return; int bar_prev=BarToCurrent(symbol_name,timeframe_src,shift+1); int bar_next=(shift>0 ? BarToCurrent(symbol_name,timeframe_src,shift-1) : 0); if(bar_prev==WRONG_VALUE || bar_curr==WRONG_VALUE || bar_next==WRONG_VALUE) return; buffer_dest[bar_curr]=buffer_src[shift]; if(mode==DRAW_MODE_STEPS) for(int j=bar_curr; j>=bar_next; j--) buffer_dest[j]=buffer_dest[bar_curr]; else { if(bar_prev>rates_total-1) return; for(int j=bar_prev; j>=bar_curr; j--) buffer_dest[j]=EquationDirect(bar_prev,buffer_dest[bar_prev],bar_curr,buffer_dest[bar_curr],j); if(shift==0) for(int j=bar_curr; j>=0; j--) buffer_dest[j]=buffer_dest[bar_curr]; } } //+------------------------------------------------------------------+ //| 将指定时间框架的条形图返回为当前时间框架的条形图。 //+------------------------------------------------------------------+ int BarToCurrent(const string symbol_name,const ENUM_TIMEFRAMES timeframe_src,const int shift,bool exact=false) { datetime time=Time(symbol_name,timeframe_src,shift); return(time!=0 ? BarShift(symbol_name,Period(),time,exact) : WRONG_VALUE); } //+------------------------------------------------------------------+ //| 返回条形图的时间偏移量 //| https://www.mql5.com/ru/forum/743/page11#comment_7010041 | //+------------------------------------------------------------------+ int BarShift(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const datetime time,bool exact=false) { int res=Bars(symbol_name,timeframe,time+1,UINT_MAX); if(exact) if((timeframe!=PERIOD_MN1 || time>TimeCurrent()) && res==Bars(symbol_name,timeframe,time-PeriodSeconds(timeframe)+1,UINT_MAX)) return(WRONG_VALUE); return res; } //+------------------------------------------------------------------+ //| 返回时间| //+------------------------------------------------------------------+ datetime Time(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int shift) { datetime array[]; ArraySetAsSeries(array,true); return(CopyTime(symbol_name,timeframe,shift,1,array)==1 ? array[0] : 0); } //+------------------------------------------------------------------+ //| 返回关闭| //+------------------------------------------------------------------+ double Close(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int shift) { double array[]; ArraySetAsSeries(array,true); return(CopyClose(symbol_name,timeframe,shift,1,array)==1 ? array[0] : 0); } //+------------------------------------------------------------------+ //| 返回 Tick Volume| //+------------------------------------------------------------------+ long TickVolume(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int shift) { long array[]; ArraySetAsSeries(array,true); return(CopyTickVolume(symbol_name,timeframe,shift,1,array)==1 ? array[0] : 0); } //+------------------------------------------------------------------+ //| 直线方程| //+------------------------------------------------------------------+ double EquationDirect(const int left_bar,const double left_price,const int right_bar,const double right_price,const int bar_to_search) { return(right_bar==left_bar ? left_price : (right_price-left_price)/(right_bar-left_bar)*(bar_to_search-left_bar)+left_price); } //+------------------------------------------------------------------+ //| 将时间框架转换为字符串| //+------------------------------------------------------------------+ string TimeframeToString(const ENUM_TIMEFRAMES timeframe) { return StringSubstr(EnumToString(timeframe),7); } //+------------------------------------------------------------------+ //| 简单移动平均线| //+------------------------------------------------------------------+ double GetSMA(const int rates_total,const int index,const int period,const double &price[],const bool as_series=true) { //--- double result=0.0; //--- 检查位置 bool check_index=(as_series ? index<=rates_total-period-1 : index>=period-1); if(period<1 || !check_index) return 0; //--- 计算值 for(int i=0; i<period; i++) result+=(as_series ? price[index+i]: price[index-i]); //--- return(result/period); } //+------------------------------------------------------------------+ //| 计算 SVSI| //+------------------------------------------------------------------+ void SVSI(const int rates_total,const int shift,const int smoothihg,const double &buffer_pos[],const double &buffer_neg[],double &buffer_svsi[]) { double AvgPosVol=GetSMA(rates_total,shift,smoothihg,buffer_pos); double AvgNegVol=GetSMA(rates_total,shift,smoothihg,buffer_neg); double svs=(AvgNegVol!=0 ? AvgPosVol/AvgNegVol : 100.0); buffer_svsi[shift]=100.0-100.0/(1.0+svs); } //+------------------------------------------------------------------+ //| 数据准备| //+------------------------------------------------------------------+ bool DataPreparing(const int shift,const ENUM_TIMEFRAMES timeframe,const double &buffer_ma[],double &buffer_pos[],double &buffer_neg[]) { double close=Close(NULL,timeframe,shift); long volume=TickVolume(NULL,timeframe,shift); if(close==0 || volume==0) return false; if(close>buffer_ma[shift]) { buffer_pos[shift]=volume/1000000.0; buffer_neg[shift]=0.0; } else if(close<buffer_ma[shift]) { buffer_neg[shift]=volume/1000000.0; buffer_pos[shift]=0.0; } else buffer_pos[shift]=buffer_neg[shift]=0; return true; } //+------------------------------------------------------------------+ // ENUM_TIMEFRAMES timeFrameGet(int period) { int _shift=(period<0?MathAbs(period):0); if(_shift>0 || period==tf_cu) period=_Period; int i; for(i=0;i<ArraySize(_tfsPer);i++) if(period==_tfsPer[i]) break; return(_tfsPer[(int)MathMin(i+_shift,ArraySize(_tfsPer)-1)]); } // //---
我想在 mt4 上用这个进行交易
SVSI_MTF:
多时间帧慢速交易量强度指数
作者: Scriptor