Я сам мучался раньше с этими точками, потом стал рисовать отрезсками линий.
Это все конечно извращения, типа "голь на выдумки хитра", но для примера можешь посмотреть
как сделан следующий код. Только лучше сначала перенеси его на свой МТ4, а потом разбирайся, -
уж очень наворачивать пришлось. Вертикальные линии можно выделять и перемещать.
На график перетаскивается мышкой.
Это все конечно извращения, типа "голь на выдумки хитра", но для примера можешь посмотреть
как сделан следующий код. Только лучше сначала перенеси его на свой МТ4, а потом разбирайся, -
уж очень наворачивать пришлось. Вертикальные линии можно выделять и перемещать.
На график перетаскивается мышкой.
#property copyright "ANG3110@latchess.com" //========================================= #property show_inputs //-------------------- extern double Days=1; extern int fn=3; //------------------------------------------ double pi=3.1415926535897932384626433832795; //------------------------------------------ double ak0,ak[10],bk[10],fx,fx1,fx0,fx01,amk; double w,sum_sin,sum_cos; int T,kt; int t0,ts,tp,te,te1; int i0,is,ip,i0n,isn,ipn; int f,fs; //****************************************** int init() { ArrayResize(ak,fn+2); ArrayResize(bk,fn+2); kt=Period()*60; t0=TimeOnDropped(); T=Days*1440/Period(); i0=iBarShift(Symbol(),Period(),t0); is=i0+T/2; ip=i0+T; ObjectCreate("VL0",0,0,t0,0); ObjectSet("VL0",OBJPROP_STYLE,STYLE_DOT); ObjectSet("VL0",OBJPROP_COLOR,Blue); ObjectCreate("VLs",0,0,Time[is],0); ObjectSet("VLs",OBJPROP_STYLE,STYLE_DOT); ObjectSet("VLs",OBJPROP_COLOR,Violet); ObjectCreate("VLp",0,0,Time[ip],0); ObjectSet("VLp",OBJPROP_STYLE,STYLE_DOT); ObjectSet("VLp",OBJPROP_COLOR,Blue); ObjectCreate("A0",2,0,Time[i0+T],Close[i0+T],Time[i0],Close[i0]); } //--------------------------------------------------------------------------------------------------- int deinit() { ObjectsDeleteAll(0,2); ObjectDelete("A0"); ObjectDelete("RCh"); ObjectDelete("VL0"); ObjectDelete("VLs"); ObjectDelete("VLp"); Comment(" "); } //******************************************************************************************************** int start() { //---- while(IsStopped()==false) { //==================================================================== if (f==1) f=2; if (f==0) { f=1; t0=ObjectGet("VL0",OBJPROP_TIME1); if (t0>Time[0]) t0=Time[0]; ts=ObjectGet("VLs",OBJPROP_TIME1); if (ts>Time[T/2]) ts=Time[T/2]; tp=ObjectGet("VLp",OBJPROP_TIME1); i0=iBarShift(Symbol(),Period(),t0); is=iBarShift(Symbol(),Period(),ts); ip=iBarShift(Symbol(),Period(),tp); if (fs==0 && i0!=i0n) fs=1; if (fs==0 && is!=isn) fs=2; if (fs==0 && ip!=ipn) fs=3; if (fs!=0) {ObjectsDeleteAll(0,2);}// RefreshRates();} if (fs==1) {T=ip-i0; is=i0+T/2; i0n=i0; fs=0;} if (fs==2) {i0=is-T/2; ip=i0+T; isn=is; fs=0;} if (fs==3) {T=ip-i0; is=i0+T/2; ipn=ip; fs=0;} } //==================================================================== if (f==2) { f=0; //========================FR========================================== w=2*pi/T; ak0=0.0; for (int i=i0; i<i0+T; i++) ak0+=Close[i]; ak0=ak0/T; for (int n=1; n<=fn; n++) { sum_cos=0.0; sum_sin=0.0; for (i=i0; i<i0+T; i++) { sum_cos+=Close[i]*MathCos(n*i*w); sum_sin+=Close[i]*MathSin(n*i*w); } ak[n]=sum_cos*2/T; bk[n]=sum_sin*2/T; } //=================================================================== for (i=0; i<T; i++) { fx=0.0; fx1=0.0; for (n=1; n<=fn; n++) { fx+=ak[n]*MathCos(n*(i+i0)*w)+bk[n]*MathSin(n*(i+i0)*w); fx1+=ak[n]*MathCos(n*(i+i0+1)*w)+bk[n]*MathSin(n*(i+i0+1)*w); } fx=ak0+fx; fx1=ak0+fx1; ObjectCreate("ar"+i,2,0,Time[i+i0+1],fx1,Time[i+i0],fx); ObjectSet("ar"+i,OBJPROP_RAY,0); if (fx>fx1) ObjectSet("ar"+i,OBJPROP_COLOR,Lime); if (fx<fx1) ObjectSet("ar"+i,OBJPROP_COLOR,Yellow); } //------------------------------------------------------- for (i=-1; i>=-T/2; i--) { fx=0.0; fx1=0.0; for (n=1; n<=fn; n++) { fx+=ak[n]*MathCos(n*(i+i0)*w)+bk[n]*MathSin(n*(i+i0)*w); fx1+=ak[n]*MathCos(n*(i+i0+1)*w)+bk[n]*MathSin(n*(i+i0+1)*w); } fx=ak0+fx; fx1=ak0+fx1; if (i+i0>=0) ObjectCreate("are"+i,2,0,Time[i+i0+1],fx1,Time[i+i0],fx); if (i+i0<0) { te=Time[i0]-i*kt; te1=Time[i0]-(i+1)*kt; ObjectCreate("are"+i,2,0,te1,fx1,te,fx); } ObjectSet("are"+i,OBJPROP_RAY,0); if (fx>fx1) ObjectSet("are"+i,OBJPROP_COLOR,Blue); if (fx<fx1) ObjectSet("are"+i,OBJPROP_COLOR,Red); } //------------------------------------------------------------------------- amk=0.0; for (n=1; n<=fn; n++) amk+=MathSqrt(ak[n]*ak[n]+bk[n]*bk[n]); Comment("amk = ",DoubleToStr(2*amk/Point,0),"\n","T = ",T,"\n","hr = ",T*Period()/60,"\n","Days = ",T*Period()/1440); //================================================================== ObjectMove("VL0",0,Time[i0],0); ObjectMove("VLs",0,Time[is],0); ObjectMove("VLp",0,Time[ip],0); ObjectCreate("A0",2,0,Time[ip],ak0,Time[i0],ak0); ObjectSet("A0",OBJPROP_RAY,0); //=================================================================== } } //-------------- return(0); } //+------------------------------------------------------------------+
Успехов!
Пока что-то в логах идёт деление на ноль и ничего не рисуется на экране.
Хотя спасибо, уже разобрался с главным вопросом. Вот переделанный скрипт, который рисует линию.
Хотя спасибо, уже разобрался с главным вопросом. Вот переделанный скрипт, который рисует линию.
//+------------------------------------------------------------------+ //| STATISTICS1.mq4 | //| Copyright © 2006, MetaQuotes Software Corp. | //| http://www.metaquotes.net | //+------------------------------------------------------------------+ #property copyright "Copyright © 2006, MetaQuotes Software Corp." #property link "http://www.metaquotes.net" //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int start() { string arrowName; int i,deletedArrows=0,arrowCounter=0; //---- deletedArrows=ObjectsDeleteAll(0,OBJ_TREND); string hline_2; for(i=100;i>=1;i--) { hline_2="hline_t_"+i; ObjectCreate(hline_2,OBJ_TREND,0,Time[i],Open[i]-0.02,Time[i-1],Open[i-1]-0.02); ObjectSet(hline_2,OBJPROP_COLOR,White); ObjectSet(hline_2,OBJPROP_STYLE,DRAW_LINE); ObjectSet(hline_2,OBJPROP_WIDTH,1); ObjectSet(hline_2,OBJPROP_BACK,true); ObjectSet(hline_2,OBJPROP_RAY,false); } //---- return(0); } //+------------------------------------------------------------------+
Для рисования отлично приспособлены индикаторы.
Можно где угодно (в т.ч. в скрипте) производить вычисления, а потом через Глоб.Перем. передать текущее значение в индикатор. Пусть себе рисует:)
Можно где угодно (в т.ч. в скрипте) производить вычисления, а потом через Глоб.Перем. передать текущее значение в индикатор. Пусть себе рисует:)
А какое максимальное число глобальных переменных допускает терминал?
Например я хочу рисовать 2 индикатора в отдельных окнах и в каждом индикаторе должно быть 1000 точек.
То есть 2000 точек терминал сможет потянуть?
И я так понимаю, что глобальной переменной не может быть массив? То есть каждый элемент массива забивается в виде отдельной глобальной переменной в терминал?
Например я хочу рисовать 2 индикатора в отдельных окнах и в каждом индикаторе должно быть 1000 точек.
То есть 2000 точек терминал сможет потянуть?
И я так понимаю, что глобальной переменной не может быть массив? То есть каждый элемент массива забивается в виде отдельной глобальной переменной в терминал?
Всё проще.
ГлобПеременных должно быть столько, сколько предполагается индикаторных линий.
На текущем тике каждой линии (и поставленному ей в соответствие индикаторному массиву) необходимо передать одно текущее значение, вычисленное скриптом.
В простом случае - одна линия, одна ГлПр.
(просто посмотрите внимательней как вообще устроен индикатор)
ГлобПеременных должно быть столько, сколько предполагается индикаторных линий.
На текущем тике каждой линии (и поставленному ей в соответствие индикаторному массиву) необходимо передать одно текущее значение, вычисленное скриптом.
В простом случае - одна линия, одна ГлПр.
(просто посмотрите внимательней как вообще устроен индикатор)
Ну так наверное ведь не получится! Мне нужно сразу иметь 1000 точек на индикаторе, вычисленных скриптом, например на периоде H1 по последним 1000 барам, а не ждать когда ещё пройдёт 1000 баров по H1, чтобы индикатор отрисовал. Да и тем более, что такой вариант возможен для индикаторов типа показа тиков, которые просто могут накапливаться индикатором через одну глобальную переменную.
Наверное вот так вот будет надёжнее и это уже проверено:
http://www.alpari-idc.ru/ru/experts/articles/20.html?id=20&printer-version=1
Наверное вот так вот будет надёжнее и это уже проверено:
http://www.alpari-idc.ru/ru/experts/articles/20.html?id=20&printer-version=1
Нет.
Каждый должен заниматься своим делом: скрипт - считать, индикатор - рисовать.
Нет никакой сложности при первом включении последовательно передать в индикатор сколько угодно данных. Нужно просто это сделать. Например, можно завести ещё одну ГлПер., кот. показывала бы состояние "наполненности" индикатора. Если пустой - 0, полный - 1.
Это значение должен отслеживать скрипт. Увидел 0 - начал передавать данные.. одно за другим, а индикатор, по мере усваивания исторических значений, может их обнулять. Увидел скрипт обнулённое - снова сообщает. Индик. снова усваивает и обнуляет, снова, снова.. Так можно передать весь комплект.
Передали комплект - установили 1 в ГлПер "наполнен" и продолжаем только на тек. значениях.
-----------------
Вообще-то, задачу можно решить многими способами.
Я сторонник академического подхода - как показывает опыт, академический подход к любому делу даёт лучший результат.
Думаю, что правильней один раз (хоть и долго) сделать сложную но корректную по сути конструкцию, но потом удобно ею пользоваться, чем (лишь бы быстрее) соорудить какую попало конструкцию, на кот. потом всё равно тратить время на заплатки, доводки, переделки и испытывать сложности при использовании.
Каждый должен заниматься своим делом: скрипт - считать, индикатор - рисовать.
Нет никакой сложности при первом включении последовательно передать в индикатор сколько угодно данных. Нужно просто это сделать. Например, можно завести ещё одну ГлПер., кот. показывала бы состояние "наполненности" индикатора. Если пустой - 0, полный - 1.
Это значение должен отслеживать скрипт. Увидел 0 - начал передавать данные.. одно за другим, а индикатор, по мере усваивания исторических значений, может их обнулять. Увидел скрипт обнулённое - снова сообщает. Индик. снова усваивает и обнуляет, снова, снова.. Так можно передать весь комплект.
Передали комплект - установили 1 в ГлПер "наполнен" и продолжаем только на тек. значениях.
-----------------
Вообще-то, задачу можно решить многими способами.
Я сторонник академического подхода - как показывает опыт, академический подход к любому делу даёт лучший результат.
Думаю, что правильней один раз (хоть и долго) сделать сложную но корректную по сути конструкцию, но потом удобно ею пользоваться, чем (лишь бы быстрее) соорудить какую попало конструкцию, на кот. потом всё равно тратить время на заплатки, доводки, переделки и испытывать сложности при использовании.
В общем я сделал следующий вариант решения моей задачи по рекомендациям указанной выше статьи. Если кому нужно, то пожалуйста, можете посмотреть. Делаем индикатор и скрипт. Индикатор STATISTICS_IND1 цепляем на график, например EURUSD (я именно под него сделал прикидки для примера) и запускаем скрипт STATISTICS1.mq4. В результате скрипт строит в отдельном индикаторном окне некоторые графические построения.
//+------------------------------------------------------------------+ //| STATISTICS_IND1.mq4 | //| Copyright © 2006, MetaQuotes Software Corp. | //| http://www.metaquotes.net | //+------------------------------------------------------------------+ #property copyright "Copyright © 2006, MetaQuotes Software Corp." #property link "http://www.metaquotes.net" #property indicator_separate_window #property indicator_buffers 1 #property indicator_color1 Red //--- buffers double ExtMapBuffer1[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int init() { //---- indicators SetIndexStyle(0,DRAW_NONE); SetIndexBuffer(0,ExtMapBuffer1); SetIndexEmptyValue(0,0.0); //---- return(0); } //+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ int deinit() { //---- //---- return(0); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int start() { int counted_bars=IndicatorCounted(); //---- ExtMapBuffer1[0]=0.01; ExtMapBuffer1[1]=-0.01; //---- return(0); } //+------------------------------------------------------------------+
//+------------------------------------------------------------------+ //| STATISTICS1.mq4 | //| Copyright © 2006, MetaQuotes Software Corp. | //| http://www.metaquotes.net | //+------------------------------------------------------------------+ #property copyright "Copyright © 2006, MetaQuotes Software Corp." #property link "http://www.metaquotes.net" //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int start() { //---- double data_for_drawing[10]; double h_centr_line=0;//положение центральной линии double h_up_line=0.01;//положение верхней линии double h_down_line=-0.01;//положение нижней линии int size_of_array=150,i; ArrayResize(data_for_drawing, size_of_array); for(i=size_of_array-1;i>=0;i--) { data_for_drawing[i]=Open[i]-1.27; } //работа с отдельным окном int IND1_window=WindowFind("STATISTICS_IND1");// номер окна индикатора STATISTICS_IND1 grafic_separate(IND1_window, data_for_drawing, h_centr_line, h_up_line, h_down_line, "Ошибки линейной регрессии"); return(0); } //+------------------------------------------------------------------+ //функция вывода графика в отдельный индикатор int grafic_separate(int window_number, double data[], double h_centr, double h_up, double h_down, string output_text) { int deletedArrows,k,size; string line_name; //очистка предыдущего рисунка deletedArrows=ObjectsDeleteAll(window_number,OBJ_TREND); deletedArrows=ObjectsDeleteAll(window_number,OBJ_TEXT); //находим размер массива size=ArraySize(data); //пишем текст line_name="text_line"; ObjectCreate(line_name, OBJ_TEXT, window_number, Time[size-StringLen(output_text)], h_centr); ObjectSetText(line_name, output_text, 8, "Arial", Yellow); //рисуем центральную горизонтальную линию line_name="с_h_line"; ObjectCreate(line_name,OBJ_TREND,window_number,Time[size-1],h_centr,Time[0],h_centr); ObjectSet(line_name,OBJPROP_COLOR,Yellow); ObjectSet(line_name,OBJPROP_STYLE,STYLE_DOT); ObjectSet(line_name,OBJPROP_WIDTH,1); ObjectSet(line_name,OBJPROP_BACK,true); ObjectSet(line_name,OBJPROP_RAY,false); //рисуем верхнюю линию line_name="с_up_line"; ObjectCreate(line_name,OBJ_TREND,window_number,Time[size-1],h_up,Time[0],h_up); ObjectSet(line_name,OBJPROP_COLOR,White); ObjectSet(line_name,OBJPROP_STYLE,STYLE_DOT); ObjectSet(line_name,OBJPROP_WIDTH,1); ObjectSet(line_name,OBJPROP_BACK,true); ObjectSet(line_name,OBJPROP_RAY,false); //рисуем нижнюю линию line_name="с_down_line"; ObjectCreate(line_name,OBJ_TREND,window_number,Time[size-1],h_down,Time[0],h_down); ObjectSet(line_name,OBJPROP_COLOR,White); ObjectSet(line_name,OBJPROP_STYLE,STYLE_DOT); ObjectSet(line_name,OBJPROP_WIDTH,1); ObjectSet(line_name,OBJPROP_BACK,true); ObjectSet(line_name,OBJPROP_RAY,false); //рисуем график for(k=size-1;k>=1;k--) { line_name="line_"+k; ObjectCreate(line_name,OBJ_TREND,window_number,Time[k],data[k]+h_centr,Time[k-1],data[k-1]+h_centr); ObjectSet(line_name,OBJPROP_COLOR,White); ObjectSet(line_name,OBJPROP_STYLE,DRAW_LINE); ObjectSet(line_name,OBJPROP_WIDTH,1); ObjectSet(line_name,OBJPROP_BACK,true); ObjectSet(line_name,OBJPROP_RAY,false); } }
Конечно, рисовать кривые линии лучше индикатором. Но если мы захотим передвинуть точки начала и конца индикаторной линии, то нам придется ждать прихода следующего тика, чтобы сработала команда start( )
или открывать правой кнопкой мыши окошко и жать на "Обновить", - это все не очень удобно, особенно на выходные, когда котировки не приходят. Чтобы кто-то эмулировал бы команду "Обновить" в индикаторном окне из скрипта - я пока не видел, хотя видимо используя что-то типа user32, - это сделать наверное можно.
Вообщем все что касается динамической работы различных построений на индикаторных графиках - в MT4 практически не решено.
или открывать правой кнопкой мыши окошко и жать на "Обновить", - это все не очень удобно, особенно на выходные, когда котировки не приходят. Чтобы кто-то эмулировал бы команду "Обновить" в индикаторном окне из скрипта - я пока не видел, хотя видимо используя что-то типа user32, - это сделать наверное можно.
Вообщем все что касается динамической работы различных построений на индикаторных графиках - в MT4 практически не решено.
Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
Заранее благодарю за помощь.