//+------------------------------------------------------------------+ //| Коррекционные уровни.mq4 | //| Copyright © 2010, sever11 | //| Realisation : http://www.komposter.me | //+------------------------------------------------------------------+ #property copyright "Copyright © 2010, sever11" #property link "http://www.komposter.me" //отрисовывает только последние данные на графике #define NO_DECISION 0 #define MOVE_UP 1 #define MOVE_UP_REVERSE 10 #define MOVE_DN 2 #define MOVE_DN_REVERSE 20 #property indicator_separate_window #property indicator_maximum 100 #property indicator_minimum 0 extern string Message1 = "Показать в глубь истории:"; extern int ShowLast = 0; extern string Message2 = "TRUE - будут показаны"; extern bool _Year = false; extern bool _Quarter = false; extern bool _Month = false; extern bool _Week = false; extern bool _Day = false; extern bool _Hour4 = false; extern bool _Hour1 = false; extern bool _Minute30 = false; extern bool _Minute15 = false; extern bool _Minute5 = false; extern bool _Minute1 = false; extern string Settings = "----Настройки отображения----"; extern int K = 8; extern int FontSize = 9; extern color FontColor = White; bool GlobalError = false; double D5 = 1.0; string prefix = "!@@#_"; int shiftX = 0; int shiftY = 0; datetime counted_bar = 0; datetime TQ[]; double CQ[]; int init() { if ( Digits == 5 || Digits == 3 ) { D5 = 10.0; } IndicatorShortName( "Коррекционные уровни" ); return(0); } int deinit() { obj_delete(); return(0); } int start() { //--------------------------------------------------------------------------------------Проверка корректности запуска if ( GlobalError ) { return(0); } //--------------------------------------------------------------------------------------Проверка необходимости перерисовки if ( iTime( Symbol(), PERIOD_M1, 0 ) <= counted_bar ) { return(0); } counted_bar = iTime( Symbol(), PERIOD_M1, 0 ); //--------------------------------------------------------------------------------------Инициализация стартовых данных int win = WindowFind( "Коррекционные уровни" ); shiftX = 5; shiftY = 15 + (FontSize + 5); CreateCaptions(win); InitQuarter(); double price_close = 0; int timer = 0; int index = 0; //--------------------------------------------------------------------------------------Начало цикла отображения //--показываем последние ShowLast закрытых периодов for ( int i = 1; i <= ShowLast + 1; i ++ ) { price_close = 0; timer = 0; index = 0; //ГОД timer = TimeYear(TimeCurrent()) + 1 - i; //--определяем год, последнюю цену которого нам нужно отыскать while( TimeYear(iTime( Symbol(), PERIOD_MN1, index )) >= timer ) //--до тех пор, пока год анализируемого бара >= нужного года { index ++; //--углубляемся //--если копать дальше некуда, отмечаем, что данных у нас нет и выходим if ( index >= iBars( Symbol(), PERIOD_MN1 ) - 1 ) { index = -1; break; } } //--если данные есть - пускаем их на анализ if ( index >= 0 ) { AnalyzeLastPeriod( iClose( Symbol(), PERIOD_MN1, index ), _Year, "Y1", i ); } else { shiftX += (FontSize*8 + 5); } //--иначе просто ничего не рисуем //КВАРТАЛ timer = ArraySize( CQ ) - 1; //--если у нас есть нужные данные - анализируем if ( i <= timer ) { AnalyzeLastPeriod( CQ[timer - i], _Quarter, "Q1", i ); } else { shiftX += (FontSize*8 + 5); } //--иначе просто ничего не рисуем //СТАНДАРТНЫЕ ПЕРИОДЫ AnalyzeLastPeriod( iClose( Symbol(), PERIOD_MN1, i ), _Month, "MN1", i ); AnalyzeLastPeriod( iClose( Symbol(), PERIOD_W1, i ), _Week, "W1", i ); AnalyzeLastPeriod( iClose( Symbol(), PERIOD_D1, i ), _Day, "D1", i ); AnalyzeLastPeriod( iClose( Symbol(), PERIOD_H4, i ), _Hour4, "H4", i ); AnalyzeLastPeriod( iClose( Symbol(), PERIOD_H1, i ), _Hour1, "H1", i ); AnalyzeLastPeriod( iClose( Symbol(), PERIOD_M30, i ), _Minute30, "M30", i ); AnalyzeLastPeriod( iClose( Symbol(), PERIOD_M15, i ), _Minute15, "M15", i ); AnalyzeLastPeriod( iClose( Symbol(), PERIOD_M5, i ), _Minute5, "M5", i ); AnalyzeLastPeriod( iClose( Symbol(), PERIOD_M1, i ), _Minute1, "M1", i ); shiftX = 5; shiftY += (FontSize + 5); } return(0); } void AnalyzeLastPeriod( double close, bool draw, string period, int start_bar ) { double upper = 0; //--верхняя граница канала double lower = 0; //--нижняя граница канала double divide = 100.0; //--коррекционная дельта double subdiv = 50.0; //--полупериод double level = 0; //--уровень к которому мы стремимся double lfilter = 0; //--нижняя грань фильтра double hfilter = 0; //--верхняя грань фильтра int decision = NO_DECISION; if ( Digits < 4 ) { divide = 1.0; } //--обрабатываем цену закрытия последнего периода, чтобы узнать к какому коррекционному уровню она стремилась upper = NormalizeDouble( close*divide, 0 ); upper = NormalizeDouble( upper/divide, Digits ); //--если цена выше полученного уровня if ( close - upper > Point/2.0 ) { //--увеличим уровень на 50 пунктов и сравним опять upper = upper + subdiv*D5*Point; //--если все еще выше, значит у нас есть нижний уровень if ( close - upper > Point/2.0 ) { lower = upper; //--а верхний будет еще выше upper = upper + subdiv*D5*Point; } //--если уже ниже, значит нижний уровень был найден изначально - возвращаем его else { lower = upper - subdiv*D5*Point; } } //--если цена ниже полученного уровня else { //--попытаемся найти нижний уровень lower = upper - subdiv*D5*Point; //--если цена все еще выше, опускаемся еще на 50 пунктов, а текущий уровень запоминаем как верхний фильтр if ( lower - close > Point/2.0 ) { upper = lower; lower = lower - subdiv*D5*Point; } } if ( draw && start_bar < 2 ) { DrawLine( start_bar + "_close_" + period, close, iTime( Symbol(), Period(), start_bar ), iTime( Symbol(), Period(), start_bar - 1 ) + Period()*(K/2)*60, STYLE_SOLID, 1, DodgerBlue ); DrawTextLabel( start_bar + "_close_" + period, iTime( Symbol(), Period(), start_bar - 1 ) + Period()*(K/2)*60, close, DodgerBlue, false ); } double toUpper = NormalizeDouble( MathAbs( close - upper ), Digits ); double toLower = NormalizeDouble( MathAbs( close - lower ), Digits ); divide = 100.0; //--если цена ближе к нижнему уровню if ( toUpper - toLower > Point/2.0 ) { level = lower; //--круглый уровень if ( MathMod( NormalizeDouble(level/Point, 0), divide*D5 ) < Point ) { lfilter = lower + 12.0*D5*Point; hfilter = lower + 31.0*D5*Point; } else { lfilter = upper - 31.0*D5*Point; hfilter = upper - 12.0*D5*Point; } if ( close - hfilter > -Point/2.0 ) { decision = MOVE_UP_REVERSE; } else { decision = MOVE_DN; } } //--если ближе к верхнему уровню else { level = upper; //--круглый уровень if ( MathMod( NormalizeDouble(level/Point, 0), divide*D5 ) < Point ) { lfilter = upper - 31.0*D5*Point; hfilter = upper - 12.0*D5*Point; } else { lfilter = lower + 12.0*D5*Point; hfilter = lower + 31.0*D5*Point; } if ( lfilter - close > -Point/2.0 ) { decision = MOVE_DN_REVERSE; } else { decision = MOVE_UP; } } if ( draw && start_bar < 2 ) { datetime time_one = iTime( Symbol(), Period(), K + start_bar ); datetime time_two = iTime( Symbol(), Period(), start_bar - 1 ); DrawLine( start_bar + "_level_" + period, level, time_one, time_two + Period()*K*60, STYLE_SOLID, 2, Red ); DrawText( start_bar + "_level_" + period, DoubleToStr( level, Digits ), time_two + Period()*(K-K/8)*60, level, 15, Red ); DrawLine( start_bar + "_lfilter_" + period, lfilter, time_one, time_two, STYLE_DOT, 1, Orange ); DrawTextLabel( start_bar + "_lfilter_" + period, time_one, lfilter, Orange, true ); DrawLine( start_bar + "_hfilter_" + period, hfilter, time_one, time_two, STYLE_DOT, 1, Orange ); DrawTextLabel( start_bar + "_hfilter_" + period, time_two, hfilter, Orange, false ); } //--выводим сообщение о нашем решении int win = WindowFind( "Коррекционные уровни" ); DrawLabel( start_bar + "_label_" + period, decision, period, win, level ); } void DrawLabel( string name, int decision, string caption, int window, double level ) { bool success = false; name = prefix + name + "_arrow"; color clr = FontColor; string str = ""; //233 - upward //234 - downward switch( decision ) { case MOVE_UP: caption = CharToStr(233); clr = Lime; str = DoubleToStr( level, Digits ); break; case MOVE_UP_REVERSE: caption = CharToStr(233); clr = Lime; str = DoubleToStr( level + 50.0*D5*Point, Digits ); break; case MOVE_DN: caption = CharToStr(234); clr = Red; str = DoubleToStr( level, Digits ); break; case MOVE_DN_REVERSE: caption = CharToStr(234); clr = Red; str = DoubleToStr( level - 50.0*D5*Point, Digits ); break; default: caption = CharToStr(76); clr = Orange; str = "Unknown"; break; } if ( ObjectFind(name) < 0 ) { success = ObjectCreate( name, OBJ_LABEL, window, 0, 0 ); } else { success = true; } if ( success ) { ObjectSetText( name, caption, FontSize, "Wingdings", clr ); ObjectSet( name, OBJPROP_XDISTANCE, shiftX ); ObjectSet( name, OBJPROP_YDISTANCE, shiftY ); ObjectSet( name, OBJPROP_CORNER, 0 ); WindowRedraw(); } shiftX += (FontSize + 5); name = name + "_digit"; if ( ObjectFind(name) < 0 ) { success = ObjectCreate( name, OBJ_LABEL, window, 0, 0 ); } else { success = true; } if ( success ) { ObjectSetText( name, str, FontSize, "Arial", clr ); ObjectSet( name, OBJPROP_XDISTANCE, shiftX ); ObjectSet( name, OBJPROP_YDISTANCE, shiftY ); ObjectSet( name, OBJPROP_CORNER, 0 ); WindowRedraw(); } shiftX += (FontSize*7); } void DrawLine( string name, double level, datetime start, datetime finit, int STL, int WDT, color CLR ) { bool success = false; name = prefix + name; if ( ObjectFind(name) < 0 ) { success = ObjectCreate( name, OBJ_TREND, 0, start, level, finit, level ); } else { success = true; } if ( success ) { ObjectSet( name, OBJPROP_RAY, false ); ObjectSet( name, OBJPROP_COLOR, CLR ); ObjectSet( name, OBJPROP_STYLE, STL ); ObjectSet( name, OBJPROP_WIDTH, WDT ); ObjectSet( name, OBJPROP_TIME1, start ); ObjectSet( name, OBJPROP_TIME2, finit ); ObjectSet( name, OBJPROP_PRICE1, level ); ObjectSet( name, OBJPROP_PRICE2, level ); WindowRedraw(); } } void DrawText( string name, string text, datetime t1, double p1, int FNT, color CLR ) { bool success = false; name = prefix + name + "_text"; if ( ObjectFind(name) < 0 ) { success = ObjectCreate( name, OBJ_TEXT, 0, t1, p1 ); } else { success = true; } if ( success ) { ObjectSet( name, OBJPROP_TIME1, t1 ); ObjectSet( name, OBJPROP_PRICE1, p1 ); ObjectSetText( name, text, FNT, "Arial", CLR ); WindowRedraw(); } } void DrawTextLabel( string name, datetime t1, double p1, color clr, bool left ) { bool success = false; name = prefix + name + "_label"; if ( ObjectFind(name) < 0 ) { success = ObjectCreate( name, OBJ_ARROW, 0, t1, p1 ); } else { success = true; } if ( success ) { ObjectSet( name, OBJPROP_TIME1, t1 ); ObjectSet( name, OBJPROP_PRICE1, p1 ); ObjectSet( name, OBJPROP_COLOR, clr ); if ( !left ) { ObjectSet( name, OBJPROP_ARROWCODE, SYMBOL_RIGHTPRICE ); } else { ObjectSet( name, OBJPROP_ARROWCODE, SYMBOL_LEFTPRICE ); } WindowRedraw(); } } void obj_delete() { int total = ObjectsTotal() - 1; string name = ""; for ( int i = total; i >= 0; i -- ) { name = ObjectName(i); if ( ObjectFind(name) < 0 ) { continue; } if ( StringFind( name, prefix ) >= 0 ) { ObjectDelete(name); } } } void CreateCaptions( int win ) { string caps[11] = { "Y1", "Q1", "MN1", "W1", "D1", "H4", "H1", "M30", "M15", "M5", "M1" }; int shftX = 5; string name = ""; for ( int i = 0; i < 11; i ++ ) { name = prefix + caps[i]; if ( ObjectFind(name) < 0 ) { ObjectCreate( name, OBJ_LABEL, win, 0, 0 ); } ObjectSet( name, OBJPROP_XDISTANCE, shftX ); ObjectSet( name, OBJPROP_YDISTANCE, 15 ); ObjectSetText( name, caps[i], FontSize, "Arial", FontColor ); shftX += (FontSize*8 + 5); } WindowRedraw(); } void InitQuarter() { ArrayResize( TQ, 0 ); ArrayResize( CQ, 0 ); datetime TC = iTime( Symbol(), PERIOD_MN1, 0 ); datetime start = iTime( Symbol(), PERIOD_MN1, iBars( Symbol(), PERIOD_MN1 ) - 1 ); if ( start < D'1971.06.01 00:00' ) { start = D'1990.01.01 00:00'; } int MC = 3; datetime search = StrToTime( DoubleToStr(TimeYear(start), 0) + ".03.01 00:00" ); if ( search < start ) { search = StrToTime( DoubleToStr(TimeYear(search), 0) + ".06.01 00:00" ); MC = 6; } if ( search < start ) { search = StrToTime( DoubleToStr(TimeYear(search), 0) + ".09.01 00:00" ); MC = 9; } if ( search < start ) { search = StrToTime( DoubleToStr(TimeYear(search), 0) + ".12.01 00:00" ); MC = 12; } if ( search < start ) { search = StrToTime( DoubleToStr(TimeYear(search)+1, 0) + ".03.01 00:00" ); } if ( search > TC ) { search = TC; } int sbar = 0; int limit = 12; int HUGE_DIGIT = 9999999; for ( int i = 0; i < HUGE_DIGIT; i ++ ) { ArrayResize( TQ, i+1 ); ArrayResize( CQ, i+1 ); sbar = iBarShift ( Symbol(), PERIOD_MN1, search ); TQ[i] = iTime ( Symbol(), PERIOD_MN1, sbar ); CQ[i] = iClose ( Symbol(), PERIOD_MN1, sbar ); limit = 12; if ( TimeMonth(TQ[i]) > MC ) { sbar ++; TQ[i] = iTime ( Symbol(), PERIOD_MN1, sbar ); CQ[i] = iClose ( Symbol(), PERIOD_MN1, sbar ); } while ( TimeMonth(TQ[i]) < MC && limit > 0 ) { limit --; TQ[i] = iTime ( Symbol(), PERIOD_MN1, sbar ); CQ[i] = iClose ( Symbol(), PERIOD_MN1, sbar ); sbar --; } if ( search == TC ) { break; } if ( MC == 3 ) { search = StrToTime( DoubleToStr ( TimeYear(search), 0 ) + ".06.01 00:00" ); MC = 6; } else if ( MC == 6 ) { search = StrToTime( DoubleToStr ( TimeYear(search), 0 ) + ".09.01 00:00" ); MC = 9; } else if ( MC == 9 ) { search = StrToTime( DoubleToStr ( TimeYear(search), 0 ) + ".12.01 00:00" ); MC = 12; } else if ( MC == 12 ) { search = StrToTime( DoubleToStr ( TimeYear(search) + 1, 0 ) + ".03.01 00:00" ); MC = 3; } if ( search > TC ) { search = TC; MC = TimeMonth(TC); } } }