I want to adjust some indicator parameter on the fly using template because structure doesn't change just the parameter values. So is it possible to load (and reload/refresh) a template programmatically ?
- Is it possible to add a symbol that doesn't already exist and programmatically ?
- Is it possible to add/remove an indicator programmatically ?
- reloading template
yes winapi (& what about WindowRedraw())
Thanks very much. Not sure to understand fully: should I just use WindowRedraw() ?
By winapi do you mean low level programming win32 (I'm really not expert at that :( )
This has been discussed in other threads with no real consensus. Instead, what I do is drop the indicators and have the EA draw the indicator values on the chart. Thus they always match.
//+------------------------------------------------------------------+ //| EA equivalent of indicator buffers | //+------------------------------------------------------------------+ /* Example 1: * if (...) Ordermodify(...); * Polyline("SL"+(oo.ticket%99), oo.SL, Color.SL, 0); * * Example 2: * double ELineCurr = iMA(NULL,0, ELine.Period, 0, MODE_EMA, PRICE_CLOSE, 1); * string pln=Polyline("ELine", ELineCurr, Color.ELine, 1); * ObjectSet(pln, OBJPROP_STYLE, STYLE_DOT); * ObjectSetText(pln, "ELine="+DoubleToStr(ELineCurr,Digits), 10); ******************************************************************************/ #define POLYLINE_MAX 20 // Must match priceXX[] string lineName[POLYLINE_MAX]; // Common to Polyline and PolyLineDelete. string Polyline(string name, double price, color clr, int shift=0){ if (!Show.Objects) return(""); // Return the actual object name for static int LRU[POLYLINE_MAX]; // further modifications, E.G. style for (int idx=0; idx < POLYLINE_MAX; idx++){ bool new = lineName[idx] != name; if (!new) break; } if (new){ for (idx=0; idx < POLYLINE_MAX; idx++) LRU[idx]++; idx=ArrayMaximum(LRU); lineName[idx]=name; } LRU[idx] = 0; double price00[], price01[], price02[], price03[], price04[], price05[], price06[], price07[], price08[], price09[], price10[], price11[], price12[], price13[], price14[], price15[], price16[], price17[], price18[], price19[]; switch (idx){ case 0: return(PLHelper(name, price, clr, idx, new, shift, price00)); case 1: return(PLHelper(name, price, clr, idx, new, shift, price01)); case 2: return(PLHelper(name, price, clr, idx, new, shift, price02)); case 3: return(PLHelper(name, price, clr, idx, new, shift, price03)); case 4: return(PLHelper(name, price, clr, idx, new, shift, price04)); case 5: return(PLHelper(name, price, clr, idx, new, shift, price05)); case 6: return(PLHelper(name, price, clr, idx, new, shift, price06)); case 7: return(PLHelper(name, price, clr, idx, new, shift, price07)); case 8: return(PLHelper(name, price, clr, idx, new, shift, price08)); case 9: return(PLHelper(name, price, clr, idx, new, shift, price09)); case 10: return(PLHelper(name, price, clr, idx, new, shift, price10)); case 11: return(PLHelper(name, price, clr, idx, new, shift, price11)); case 12: return(PLHelper(name, price, clr, idx, new, shift, price12)); case 13: return(PLHelper(name, price, clr, idx, new, shift, price13)); case 14: return(PLHelper(name, price, clr, idx, new, shift, price14)); case 15: return(PLHelper(name, price, clr, idx, new, shift, price15)); case 16: return(PLHelper(name, price, clr, idx, new, shift, price16)); case 17: return(PLHelper(name, price, clr, idx, new, shift, price17)); case 18: return(PLHelper(name, price, clr, idx, new, shift, price18)); case 19: return(PLHelper(name, price, clr, idx, new, shift, price19)); } } string PLHelper( string name, double price, color clr, int idx, bool new , int shift, double& mem[] ){ datetime t0 = Time[shift]; static datetime timeL[POLYLINE_MAX]; if (timeL[idx] < Time[shift+1]) new = true; // Missing bar(s), leave a gap. /**/ if (new){ ArrayResize(mem, 2); mem[1] = price; static datetime timeF[POLYLINE_MAX]; timeF[idx] = Time[shift]; static color clrLn[POLYLINE_MAX]; clrLn[idx] = clr; static int segNo[POLYLINE_MAX]; segNo[idx]++; t0+=Period()*60; } // One bar wide to be visual else if (clrLn[idx] != clr){ ArrayResize(mem, 2); mem[1] = mem[0]; timeF[idx] = timeL[idx]; clrLn[idx] = clr; segNo[idx]++; } else if (timeL[idx] < t0){ // New bar, remember point. if (!ResizeBuffer(mem, ArraySize(mem)+1)) return(""); } mem[0] = price; string objName = name+"-"+segNo[idx]; timeL[idx] = t0; int firstBar = ArraySize(mem)-1; /**/ if(ObjectMove(objName, 1, t0, price)) ObjectMove(objName, 0, timeF[idx], mem[firstBar]); else if (!ObjectCreate( objName, OBJ_TREND, WINDOW_MAIN // New or tmplt. , timeF[idx], mem[firstBar], t0, price )){ Alert( "ObjectCreate(", objName, ",Trend) [1] failed: ",GetLastError());return;} else if (!ObjectSet( objName, OBJPROP_RAY, false )) Alert( "ObjectSet(", objName, ",Ray) [1] failed: ", GetLastError()); if (!ObjectSet( objName, OBJPROP_COLOR, clrLn[idx] )) Alert( "ObjectSet(", objName, ",Color) [2] failed: ", GetLastError()); double maxError=0; for (int pos=1; pos < firstBar; pos++){ double error=MathAbs(ObjectGetValueByShift(objName, pos+shift)-mem[pos]); if (error > maxError){ maxError=error; int maxBar=pos; } } if (maxError >= pips2dbl){ // Split the line into two segments at max. if (!ObjectMove(objName, 1, Time[shift+maxBar], mem[maxBar])) Alert( "ObjectMove(", objName, ",Trend) [1] failed: ", GetLastError()); ArrayResize(mem, maxBar+1); // Drop firstBar..(maxBar+1) timeF[idx] = Time[shift+maxBar]; segNo[idx]++; objName=name+"-"+segNo[idx]; /**/ if(ObjectMove(objName, 0, timeF[idx], mem[maxBar])) ObjectMove(objName, 1, t0, price); else if (!ObjectCreate( objName, OBJ_TREND, WINDOW_MAIN , timeF[idx], mem[maxBar], t0, price )) Alert( "ObjectCreate(", objName, ",Trend) [2] failed: ", GetLastError()); else if (!ObjectSet( objName, OBJPROP_RAY, false )) Alert( "ObjectSet(", objName, ",Ray) [2] failed: ", GetLastError()); else if (!ObjectSet( objName, OBJPROP_COLOR, clrLn[idx] )) Alert( "ObjectSet(", objName, ",Color) [3] failed: ", GetLastError()); } // Split the line into two segments at the max. return(objName); } // PLHelper void PolyLineDelete(string name){ for (int idx=0; idx < POLYLINE_MAX; idx++) if (lineName[idx] == name){ lineName[idx] = ""; break; } for(int obj=ObjectsTotal()-1; obj >= 0; obj--){ string objectName = ObjectName(obj); if (StringFind(objectName, name) == 0) ObjectDelete(objectName); } } bool ResizeBuffer(double buffer[], int size){ if (ArraySize(buffer) != size){ ArraySetAsSeries(buffer, false); // Shift values B[2]=B[1]; B[1]=B[0] if (ArrayResize(buffer, size) <= 0){ trading.disabled = "ArrayResize [1] failed: "+GetLastError(); return(false); } ArraySetAsSeries(buffer, true); } return(true); }
//++++ These are adjusted for 5 digit brokers. double pips2points, // slippage 3 pips 3=points 30=points pips2dbl; // Stoploss 15 pips 0.0015 0.00150 int Digits.pips; // DoubleToStr(dbl/pips2dbl, Digits.pips) int init(){ if (Digits == 5 || Digits == 3){ // Adjust for five (5) digit brokers. pips2dbl = Point*10; pips2points = 10; Digits.pips = 1; } else { pips2dbl = Point; pips2points = 1; Digits.pips = 0; } // OrderSend(... Slippage.Pips * pips2points, Bid - StopLossPips * pips2dbl }I even write separate window type indicator as a price overlay:
/*++++ Draw STC line overlay price*/{ PolyLineDelete(StcName); double stcSell = 1.-STC.Buy, buying = MathMax(STC.Buy, stcSell), selling = MathMin(STC.Buy, stcSell), top = WindowPriceMax(), bottom = WindowPriceMin(), range = top-bottom; top -= range*0.05; bottom += range*0.05; range = top-bottom; shiftChart =WindowFirstVisibleBar(); shiftChartEnd =shiftChart -WindowBarsPerChart(); if (shiftChartEnd<0) shiftChartEnd = 0; // Tester/shift datetime TimeChartLeft = Time[shiftChart]; for(shiftRB = 0; TimeChartLeft < Time.rb[shiftRB]; shiftRB++){} // Find RB. double stcPrev = stc.buffer[shiftRB], stc = stcPrev; for (;shiftChart >= shiftChartEnd; shiftChart--){ Tsc=Time[shiftChart]; while(true){ color clrNew, clrOld; double cross; /**/ if (stc > buying){ clrNew=Color.Buy; cross= buying; } else if (stc < selling){ clrNew=Color.Sell; cross=selling; } else clrNew=Color.STC; /**/ if (stcPrev > buying){ clrOld=Color.Buy; cross= buying; } else if (stcPrev < selling){ clrOld=Color.Sell; cross=selling; } else clrOld=Color.STC; if (clrNew != clrOld && stcPrev != cross){ double stcOnPrice = cross * range + bottom; string pln = Polyline(StcName, stcOnPrice, clrOld, shiftChart); ObjectSet(pln, OBJPROP_STYLE, STYLE_DOT); ObjectSetText(pln, "Stc="+DoubleToStr(stcPrev,2), 10); stcPrev = cross; continue; } stcOnPrice = stc * range + bottom; pln=Polyline(StcName, stcOnPrice, clrNew, shiftChart); ObjectSet(pln, OBJPROP_STYLE, STYLE_DOT); ObjectSetText(pln, "Stc="+DoubleToStr(stc,2), 10); stcPrev = stc; if (shiftRB == 0 ) break; // Last RB painted. if (Tsc < Time.rb[shiftRB-1]) break; // Next RB on next chart bar shiftRB--; // Next RB on same bar. stc = stc.buffer[shiftRB]; } } /*---- Draw STC line overlay price*/}
Minor restructuring/enhancement.
string PLHelper( string name, double price, color clr, int idx, bool new , int shift, double& mem[] ){ datetime t0 = Time[shift]; static datetime timeL[POLYLINE_MAX]; if (timeL[idx] < Time[shift+1]) new = true; // Missing bar(s), leave a gap. /**/ if (new){ if (!ResizeBuffer(mem, 2)) return(""); mem[1] = price; static datetime timeF[POLYLINE_MAX]; timeF[idx] = t0; static color clrLn[POLYLINE_MAX]; clrLn[idx] = clr; static int segNo[POLYLINE_MAX]; segNo[idx]++; } else if (clrLn[idx] != clr){ ArrayResize(mem, 2); // Series==true; mem[1] = mem[0]; timeF[idx] = timeL[idx]; clrLn[idx] = clr; segNo[idx]++; } else if (timeL[idx] < t0){ // New bar, remember point. if (!ResizeBuffer(mem, ArraySize(mem)+1)) return(""); } mem[0] = price; string objName = name+"_"+RJust(segNo[idx],3); timeL[idx] = t0; int firstBar = ArraySize(mem)-1; if (t0 != timeF[idx]) TLine(objName, timeF[idx], mem[firstBar], t0, price, clrLn[idx]); else TLine(objName, t0-Period()*60, mem[firstBar] // One bar wide , t0, price, clrLn[idx]); // to be visual double maxError=0; for (int pos=1; pos < firstBar; pos++){ double error=MathAbs(ObjectGetValueByShift(objName, pos+shift)-mem[pos]); if (error > maxError){ maxError=error; int maxBar=pos; } } if (maxError >= pips2dbl){ // Split the line into two segments at max. TLine(objName, timeF[idx], mem[firstBar], Time[shift+maxBar], mem[maxBar], clrLn[idx]); ArrayResize(mem, maxBar+1); // Drop firstBar..(maxBar+1) timeF[idx] = Time[shift+maxBar]; segNo[idx]++; objName=name+"_"+RJust(segNo[idx],3); TLine(objName, timeF[idx], mem[maxBar], t0, price, clrLn[idx]); } // Split the line into two segments at the max. return(objName); } // PLHelper void TLine( string name, datetime T0, double P0, datetime T1, double P1 , color clr, bool ray=false ){ #define WINDOW_MAIN 0 if (!Show.Objects) return; /**/ if(ObjectMove( name, 0, T0, P0 )) ObjectMove(name, 1, T1, P1); else if(!ObjectCreate( name, OBJ_TREND, WINDOW_MAIN, T0, P0, T1, P1 )) Alert("ObjectCreate(",name,",TREND) failed: ", GetLastError() ); else if (!ObjectSet( name, OBJPROP_RAY, ray )) Alert("ObjectSet(", name, ",Ray) failed: ", GetLastError()); if (!ObjectSet(name, OBJPROP_COLOR, clr )) // Allow color change Alert("ObjectSet(", name, ",Color) [2] failed: ", GetLastError()); string P0t = PriceToStr(P0); if (MathAbs(P0 - P1) >= Point) P0t = StringConcatenate(P0t, " to ", PriceToStr(P1)); if (!ObjectSetText(name, P0t, 10)) Alert("ObjectSetText(",name,") [2] failed: ", GetLastError()); } string PriceToStr(double p){ string pFrc = DoubleToStr(p, Digits); if(Digits.pips==0) return(pFrc); string pPip = DoubleToStr(p, Digits-1); if (pPip+"0" == pFrc) return(pPip); return(pFrc); } string RJust(string s, int size, string fill="0"){ while( StringLen(s) < size ) s = fill + s; return(s); }
WHRoeder:
Minor restructuring/enhancement.
This solution is for EA you have source code ? What if I don't ?
Minor restructuring/enhancement.
I modified the code again to allow overlays, FWIW
//+------------------------------------------------------------------+ //| EA equivalent of indicator buffers | //+------------------------------------------------------------------+ /* Example 1: * if (...) Ordermodify(...); * Polyline("SL"+(oo.ticket%99), oo.SL, Color.SL, 0); * * Example 2: * double ELineCurr = iMA(NULL,0, ELine.Period, 0, MODE_EMA, PRICE_CLOSE, 1); * string pln=Polyline("ELine", ELineCurr, Color.ELine, 1); * ObjectSet(pln, OBJPROP_STYLE, STYLE_DOT); * ObjectSetText(pln, "ELine="+DoubleToStr(ELineCurr,Digits), 10); ******************************************************************************/ #define POLYLINE_MAX 30 // Must match valueXX[] string lineName[POLYLINE_MAX]; // Common to Polyline/PolylineDelete and helper. string Polyline(string name, double value, color clr, int shift=0, double indiMin=INF, double indiMax=INF, double chrtMin=INF, double chrtMax=INF){ if (!Show.Objects) return(""); // Return the actual object name for static int LRU[POLYLINE_MAX]; // further modifications, E.G. style for (int iLine=0; iLine < POLYLINE_MAX; iLine++){ bool isNew = lineName[iLine] != name; if (!isNew) break; } if (isNew){ for (iLine=0; iLine < POLYLINE_MAX; iLine++) LRU[iLine]++; iLine=ArrayMaximum(LRU); lineName[iLine]=name; } LRU[iLine] = 0; double value00[], value01[], value02[], value03[], value04[], value05[], value06[], value07[], value08[], value09[], value10[], value11[], value12[], value13[], value14[], value15[], value16[], value17[], value18[], value19[], value20[], value21[], value22[], value23[], value24[], value25[], value26[], value27[], value28[], value29[]; switch (iLine){ case 0: return(PLHelper(value00, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 1: return(PLHelper(value01, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 2: return(PLHelper(value02, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 3: return(PLHelper(value03, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 4: return(PLHelper(value04, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 5: return(PLHelper(value05, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 6: return(PLHelper(value06, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 7: return(PLHelper(value07, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 8: return(PLHelper(value08, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 9: return(PLHelper(value09, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 10: return(PLHelper(value10, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 11: return(PLHelper(value11, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 12: return(PLHelper(value12, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 13: return(PLHelper(value13, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 14: return(PLHelper(value14, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 15: return(PLHelper(value15, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 16: return(PLHelper(value16, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 17: return(PLHelper(value17, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 18: return(PLHelper(value18, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 19: return(PLHelper(value19, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 20: return(PLHelper(value20, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 21: return(PLHelper(value21, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 22: return(PLHelper(value22, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 23: return(PLHelper(value23, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 24: return(PLHelper(value24, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 25: return(PLHelper(value25, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 26: return(PLHelper(value26, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 27: return(PLHelper(value27, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 28: return(PLHelper(value28, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); case 29: return(PLHelper(value29, value, clr, iLine, isNew, shift, indiMin, indiMax, chrtMin, chrtMax)); } /*NOTREACHED*/ } // Polyline string PLHelper( double& mem[], double value0, color clr, int iLine, bool isNew, int shift, double indiMin, double indiMax, double chrtMin, double chrtMax ){ string name = lineName[iLine]; double price0 = value0; if (indiMin < INF){ if (chrtMin == INF) chrtMin = WindowPriceMin(); if (chrtMax == INF) chrtMax = WindowPriceMax(); price0 = (value0 - indiMin) / (indiMax - indiMin) * (chrtMax - chrtMin) + chrtMin; } datetime t0 = Time[shift]; static datetime timeL[POLYLINE_MAX]; if (!isNew){ if (timeL[iLine] < Time[shift+1]){ // Missing bar(s), leave a gap. isNew = true; } else if (Time[shift] < timeL[iLine]){ // Redrawing earlier bars. isNew = true; for(int iObj=ObjectsTotal()-1; iObj >= 0; iObj--){ string on = ObjectName(iObj); if (StringFind(on, name) == 0) ObjectDelete(on); } } } if (isNew){ if (!ResizeBuffer(mem, 2)) return(""); mem[1] = price0; static datetime timeF[POLYLINE_MAX]; timeF[iLine] = t0; static color clrLn[POLYLINE_MAX]; clrLn[iLine] = clr; static int segNo[POLYLINE_MAX]; segNo[iLine]++; } else if (clrLn[iLine] != clr){ ArrayResize(mem, 2); // Series==true; mem[1] = mem[0]; timeF[iLine] = timeL[iLine]; clrLn[iLine] = clr; segNo[iLine]++; } else if (timeL[iLine] < t0){ // New bar, remember point if (!ResizeBuffer(mem, ArraySize(mem)+1)) return(""); } mem[0] = price0; timeL[iLine] = t0; int iFirst = ArraySize(mem)-1; double priceF = mem[iFirst], valueF = priceF; if (indiMin < INF){ valueF = (priceF - chrtMin) / (chrtMax - chrtMin) * (indiMax - indiMin) + indiMin; } datetime Tf = timeF[iLine]; // One bar wide if (t0 == Tf) Tf += IfI(-1, +1, shift==0)*60*Period(); // to be visual string objName = name+"_"+RJust(segNo[iLine],3); TLine(objName, Tf, priceF, t0, price0, clr, valueF, value0); double maxError=0; for (int iMem=1; iMem < iFirst; iMem++){ double hight = ObjectGetValueByShift(objName, iMem+shift), error = MathAbs(hight - mem[iMem]); if (error > maxError){ maxError = error; int iMaxError = iMem; } } if (maxError >= pips2dbl){ // Split the line into two segments at max. double priceM = mem[iMaxError], valueM = priceM; if (indiMin < INF){ valueM = (priceM - chrtMin) / (chrtMax - chrtMin) * (indiMax - indiMin) + indiMin; } TLine(objName, timeF[iLine], priceF, Time[iMaxError+shift], priceM, clr, valueF, valueM); ArrayResize(mem, iMaxError+1); // Drop iFirst..(iMaxError+1) timeF[iLine] = Time[iMaxError+shift]; segNo[iLine]++; objName=name+"_"+RJust(segNo[iLine], 3); TLine(objName, timeF[iLine], priceM, t0, price0, clr, valueM, value0); } // Split the line into two segments at the max. return(objName); } // PLHelper
Overlay call like this
#define WPR_NAME "wpr" double bottom = WindowPriceMin(), top = MathMax(WindowPriceMax(), bottom+pips2dbl),// Div0 topQuarter = (3*top + bottom)/4., botQuarter = (top + 3*bottom)/4.; int iVisible = WindowFirstVisibleBar(), iVisEnd = MathMaxI( iVisible-WindowBarsPerChart(),0);// Shft static bool drawOnTop = false; if (Bid >= topQuarter) drawOnTop = false; // Hysteresis - previous else if (Bid <= botQuarter) drawOnTop = true; // location otherwise. if (drawOnTop) bottom = topQuarter; else top = botQuarter; for(iWpr = MathMinI(iWprBegin, iVisible); iWpr >= iVisEnd; iWpr--) Polyline( WPR_NAME, wprValue[iWpr], Color.Wpr, iWpr, 0., 100., bottom, top );
![MQL5 - Language of trade strategies built-in the MetaTrader 5 client terminal](https://c.mql5.com/i/registerlandings/logo-2.png)
You are missing trading opportunities:
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
Registration
Log in
You agree to website policy and terms of use
If you do not have an account, please register