Gamestudio Links
Zorro Links
Newest Posts
optimize global parameters SOLVED
by dBc. 09/27/25 17:07
ZorroGPT
by TipmyPip. 09/27/25 10:05
Release 2.68 replacement of the .par format
by Martin_HH. 09/23/25 20:48
assetHistory one candle shift
by jcl. 09/21/25 11:36
Plugins update
by Grant. 09/17/25 16:28
AUM Magazine
Latest Screens
Rocker`s Revenge
Stug 3 Stormartillery
Iljuschin 2
Galactic Strike X
Who's Online Now
0 registered members (), 18,175 guests, and 5 spiders.
Key: Admin, Global Mod, Mod
Newest Members
krishna, DrissB, James168, Ed_Love, xtns
19168 Registered Users
Previous Thread
Next Thread
Print Thread
Rate Thread
Page 2 of 2 1 2
Re: MT4 Indicator Conversion [Re: Mandark] #437924
03/01/14 16:14
03/01/14 16:14
Joined: Feb 2014
Posts: 73
Montreal, Qc Canada
F
Finstratech Offline
Junior Member
Finstratech  Offline
Junior Member
F

Joined: Feb 2014
Posts: 73
Montreal, Qc Canada
Here is the guy that developed "TMA"
www.forex-tsd.com/metatrader-4/32719-triangular-moving-average-tma.html
explaining what it is.
And no, it's not a form of Keltner channel.

Re: MT4 Indicator Conversion [Re: Finstratech] #437926
03/01/14 16:27
03/01/14 16:27
Joined: Feb 2014
Posts: 11
M
Mandark Offline OP
Newbie
Mandark  Offline OP
Newbie
M

Joined: Feb 2014
Posts: 11
I have read that post as well, it starts off talking about the midline (and how it is more similar to the a linear weighted average than a triangular moving average. If you read that same post the author brings in the upper and lower Keltner bands as a signal around page 21-23.

Re: MT4 Indicator Conversion [Re: Mandark] #437958
03/03/14 08:59
03/03/14 08:59
Joined: Jul 2000
Posts: 28,022
Frankfurt
jcl Offline

Chief Engineer
jcl  Offline

Chief Engineer

Joined: Jul 2000
Posts: 28,022
Frankfurt
If it's the Keltner bands, the ATRS is used for the distance. The code is then:

Code:
vars Price = series(price());
int Period = 5;
vars Trimavar = series(Trima(Price,Period));
var upper = Trimavar[0]+BandsDeviations*ATRS(Period);
var lower = Trimavar[0]-BandsDeviations*ATRS(Period);




Re: MT4 Indicator Conversion [Re: jcl] #439089
03/26/14 14:28
03/26/14 14:28
Joined: May 2013
Posts: 245
S
swingtraderkk Offline
Member
swingtraderkk  Offline
Member
S

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.

Code:
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.

Code:
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.

Page 2 of 2 1 2

Moderated by  Petra 

Powered by UBB.threads™ PHP Forum Software 7.7.1