1 registered members (dBc),
17,982
guests, and 5
spiders. |
Key:
Admin,
Global Mod,
Mod
|
|
|
Re: MT4 Indicator Conversion
[Re: jcl]
#439089
03/26/14 14:28
03/26/14 14:28
|
Joined: May 2013
Posts: 245
swingtraderkk
Member
|
Member
Joined: May 2013
Posts: 245
|
Dear all, Meant to come back to this thread, but only getting round to it now. I've had a look at a version of TMA + CG (there are a few around), it appears very accurate on MT4, but of course it repaints. None the less I like the idea of a TMA with bands above and below.
extern string TimeFrame = "current time frame";
extern int HalfLength = 56;
extern int Price = PRICE_WEIGHTED;
extern double BandsDeviations = 2.5;
extern bool showPrice = true;
//
//
//
//
//
double tmBuffer[];
double upBuffer[];
double dnBuffer[];
double wuBuffer[];
double wdBuffer[];
double upLevel[];
double dnLevel[];
//
//
//
//
//
string IndicatorFileName;
bool calculatingTma = false;
bool returningBars = false;
int timeFrame;
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
//
//
int init()
{
timeFrame = stringToTimeFrame(TimeFrame);
HalfLength = MathMax(HalfLength,1);
IndicatorBuffers(7);
SetIndexBuffer(0,tmBuffer); SetIndexDrawBegin(0,HalfLength);
SetIndexBuffer(1,upBuffer); SetIndexDrawBegin(1,HalfLength);
SetIndexBuffer(2,dnBuffer); SetIndexDrawBegin(2,HalfLength);
SetIndexBuffer(3,dnLevel); SetIndexStyle(3,DRAW_LINE);
SetIndexBuffer(4,upLevel); SetIndexStyle(4,DRAW_LINE);
SetIndexStyle(3,DRAW_LINE,STYLE_DOT,1);
SetIndexStyle(4,DRAW_LINE,STYLE_DOT,1);
SetIndexBuffer(5,wuBuffer);
SetIndexBuffer(6,wdBuffer);
if(TimeFrame=="calculateTma") { calculatingTma=true; return(0); }
if(TimeFrame=="returnBars") { returningBars=true; return(0); }
IndicatorFileName=WindowExpertName();
return(0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int deinit()
{
for(int i=ObjectsTotal()-1; i>=0; i--)
{
if(StringSubstr(ObjectName(i),0,4)=="band")
ObjectDelete(ObjectName(i));
}
return(0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
//
//
//
//
//
int start()
{
int counted_bars=IndicatorCounted();
int i,limit;
if(counted_bars<0) return(-1);
if(counted_bars>0) counted_bars--;
limit=MathMin(Bars-1,Bars-counted_bars+HalfLength);
if(returningBars) { tmBuffer[0] = limit; return(0); }
if(calculatingTma) { calculateTma(limit); return(0); }
if(timeFrame>Period()) limit=MathMax(limit,MathMin(Bars-1,iCustom(NULL,timeFrame,IndicatorFileName,"returnBars",0,0)*timeFrame/Period()));
//
//
//
//
//
for(i=limit; i>=0; i--)
{
int shift1 = iBarShift(NULL,timeFrame,Time[i]);
datetime time1 = iTime (NULL,timeFrame,shift1);
double level;
tmBuffer[i] = iCustom(NULL,timeFrame,IndicatorFileName,"calculateTma",HalfLength,Price,BandsDeviations,0,shift1);
upBuffer[i] = iCustom(NULL,timeFrame,IndicatorFileName,"calculateTma",HalfLength,Price,BandsDeviations,1,shift1);
dnBuffer[i] = iCustom(NULL,timeFrame,IndicatorFileName,"calculateTma",HalfLength,Price,BandsDeviations,2,shift1);
level=(upBuffer[i]-dnBuffer[i])*20/100; // other lines take away 20% OF DIFFERENCE IN RANGE
upLevel[i] = (upBuffer[i] - level);
dnLevel[i] = (dnBuffer[i] + level);
if(showPrice)
{
SetPrice("bandHigh",Time[0],upBuffer[0],Red);
SetPrice("bandMid",Time[0],tmBuffer[0],DimGray);
SetPrice("bandLow",Time[0],dnBuffer[0],LimeGreen);
SetPrice("bandInnerHigh",Time[0],upLevel[0],Red);
SetPrice("bandInnerLow",Time[0],dnLevel[0],LimeGreen);
}
}
return(0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void calculateTma(int limit)
{
int i,j,k;
double FullLength=2.0*HalfLength+1.0;
for(i=limit; i>=0; i--)
{
double sum = (HalfLength+1)*iMA(NULL,0,1,0,MODE_SMA,Price,i);
double sumw = (HalfLength+1);
for(j=1,k=HalfLength; j<=HalfLength; j++,k--)
{
sum += k*iMA(NULL,0,1,0,MODE_SMA,Price,i+j);
sumw += k;
if(j<=i)
{
sum += k*iMA(NULL,0,1,0,MODE_SMA,Price,i-j);
sumw += k;
}
}
tmBuffer[i]=sum/sumw;
//
//
//
//
//
double diff=iMA(NULL,0,1,0,MODE_SMA,Price,i)-tmBuffer[i];
if(i>(Bars-HalfLength-1)) continue;
if(i==(Bars-HalfLength-1))
{
upBuffer[i] = tmBuffer[i];
dnBuffer[i] = tmBuffer[i];
if(diff>=0)
{
wuBuffer[i] = MathPow(diff,2);
wdBuffer[i] = 0;
}
else
{
wdBuffer[i] = MathPow(diff,2);
wuBuffer[i] = 0;
}
continue;
}
//
//
//
//
//
if(diff>=0)
{
wuBuffer[i] = (wuBuffer[i+1]*(FullLength-1)+MathPow(diff,2))/FullLength;
wdBuffer[i] = wdBuffer[i+1]*(FullLength-1)/FullLength;
}
else
{
wdBuffer[i] = (wdBuffer[i+1]*(FullLength-1)+MathPow(diff,2))/FullLength;
wuBuffer[i] = wuBuffer[i+1]*(FullLength-1)/FullLength;
}
upBuffer[i] = tmBuffer[i] + BandsDeviations*MathSqrt(wuBuffer[i]);
dnBuffer[i] = tmBuffer[i] - BandsDeviations*MathSqrt(wdBuffer[i]);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
//
//
//
//
//
//
//
//
//
//
int stringToTimeFrame(string tfs)
{
for(int l=StringLen(tfs)-1; l>=0; l--)
{
int thechar=StringGetChar(tfs,l);
if((thechar>96 && thechar<123) || (thechar>223 && thechar<256))
tfs=StringSetChar(tfs,1,thechar-32);
else
if(thechar>-33 && thechar<0)
tfs=StringSetChar(tfs,1,thechar+224);
}
int tf=0;
if(tfs=="M1" || tfs=="1") tf=PERIOD_M1;
if(tfs=="M5" || tfs=="5") tf=PERIOD_M5;
if(tfs=="M15"|| tfs=="15") tf=PERIOD_M15;
if(tfs=="M30"|| tfs=="30") tf=PERIOD_M30;
if(tfs=="H1" || tfs=="60") tf=PERIOD_H1;
if(tfs=="H4" || tfs=="240") tf=PERIOD_H4;
if(tfs=="D1" || tfs=="1440") tf=PERIOD_D1;
if(tfs=="W1" || tfs=="10080") tf=PERIOD_W1;
if(tfs=="MN" || tfs=="43200") tf=PERIOD_MN1;
if(tf==0 || tf<Period()) tf=Period();
return(tf);
}
//+------------------------------------------------------------------+
void SetPrice(string name, datetime Tm, double Prc, color clr) {
if(ObjectFind(name) == -1) {
ObjectCreate(name, OBJ_ARROW, 0, Tm, Prc);
ObjectSet(name, OBJPROP_COLOR, clr);
ObjectSet(name, OBJPROP_WIDTH, 1);
ObjectSet(name, OBJPROP_ARROWCODE, SYMBOL_RIGHTPRICE);
} else {
ObjectSet(name, OBJPROP_TIME1, Tm);
ObjectSet(name, OBJPROP_PRICE1, Prc);
ObjectSet(name, OBJPROP_COLOR, clr);
ObjectSet(name, OBJPROP_WIDTH, 1);
ObjectSet(name, OBJPROP_ARROWCODE, SYMBOL_RIGHTPRICE);
}
}
//+------------------------------------------------------------------+
My understanding of the above, I'm a trader not a programmer, is that it calculates a triangular moving average, tmbuffer[], then calculates the bands based on a weighted average of the differences between the price and the tmbuffer. 1) I don't really understand that bit, but I think it may be where the center of gravity comes in. Jcl, I would really appreciate a mathematicians explanation of it appropriate to my mental age of 7. 2) As an aside, I also cannot understand why the author uses iMA (MT4's moving average function) with a period of 1, is that not simply the price? 3) With my limitations, I did have a crack at coding it for zorro, but am unsure if this is correct.
function run()
{
StartDate = 20140101;
EndDate = 20140130;
BarPeriod = 15;
int HalfLength = 56;
var BandsDeviations = 2.5;
vars Price = series(price());
vars tmBuffer = series(0);
vars upBuffer = series(0);
vars dnBuffer = series(0);
vars wuBuffer = series(0);
vars wdBuffer = series(0);
int i,j,k;
var FullLength = 2.0*HalfLength+1;
for (i=HalfLength; i>=0; i--)
{
var sum = (HalfLength+1)*SMA(Price+i,1);
var sumw = (HalfLength+1);
for(j=1, k=HalfLength; j<=HalfLength; j++, k--)
{
sum += k*SMA(Price+(i+j),1);
sumw += k;
if (j<=i)
{
sum += k*SMA(Price+(i-j),1);
sumw += k;
}
}
tmBuffer[0] = sum/sumw;
var diff = SMA(Price+i,1)-tmBuffer[i];
if (i> (Bar-HalfLength-1)) continue;
if (i==(Bar-HalfLength-1))
{
upBuffer[i] = tmBuffer[i];
dnBuffer[i] = tmBuffer[i];
if (diff>=0)
{
wuBuffer[i] = pow(diff,2);
wdBuffer[i] = 0;
}
else
{
wdBuffer[i] = pow(diff,2);
wuBuffer[i] = 0;
}
continue;
}
if(diff>=0)
{
wuBuffer[i] = (wuBuffer[i+1]*(FullLength-1)+pow(diff,2))/FullLength;
wdBuffer[i] = (wdBuffer[i+1]*(FullLength-1))/FullLength;
}
else
{
wdBuffer[i] = (wdBuffer[i+1]*(FullLength-1)+pow(diff,2))/FullLength;
wuBuffer[i] = wuBuffer[i+1]*(FullLength-1)/FullLength;
}
upBuffer[0] = tmBuffer[0] + BandsDeviations*sqrt(wuBuffer[0]);
dnBuffer[0] = tmBuffer[0] - BandsDeviations*sqrt(wdBuffer[0]);
}
plot("tmbuffer",tmBuffer[0],0,BLUE);
plot("upbuffer",upBuffer[0],0,RED);
plot("dnbuffer",dnBuffer[0],0,GREEN);
}
I'm not happy with the above, possibly because the plots don't repaint, but visually it does not look so impressive as the MT4 one. I'm pretty sure this can be improved on in zorro using the built in TRIMA and possibly the centre of gravity indicators, but I'd like to know if I'm on the right track and understand the band calculation a bit more first.
|
|
|
|