Here is the indicator code for MT4
/*————————————————————————————
Name: ASCTrend-Matrix.mq4
Description: Two timeframe ASCTrend Matrix 4TF:
Consists of the following indicators:
Note:
Requires that the following indicators are installed and working:
ASCTrend1i.mq4,
Change log:
2013-05-03. Xaphod, v1.01
– Fixed updating of bars on all timeframes as new data is being downloaded.
– Draw blank dot if there is not data for the bar.
2013-04-??. Xaphod, v1.00
– Derived from ‘ASCTrend1-Matrix 4TF’
————————————————————————————-*/
// Indicator properties
#property copyright “Copyright © 2012, Xaphod”
#property link “http://www.xaphod.com”
#property indicator_separate_window
#property indicator_buffers 8
#property indicator_color1 DodgerBlue
#property indicator_color2 Red
#property indicator_color3 DodgerBlue
#property indicator_color4 Red
#property indicator_minimum 0
#property indicator_maximum 0.9
//#include <xDebug.mqh>
// Win32 API
#import “user32.dll”
bool GetWindowRect(int hWnd, int& lpRect[]);
#import
#import “Kernel32.dll”
int CreateFileA(string lpFileName,int dwDesiredAccess, int dwShareMode, int lpSecurityAttributes, int dwCreationDisposition,int dwFlagsAndAttributes, int hTemplateFile);
int CloseHandle(int hObject);
#import
#define OPEN_EXISTING 3
#define FILE_SHARE_READ 1
#define GENERIC_READ 0x80000000
#define FILE_ATTRIBUTE_NORMAL 128
#define INVALID_HANDLE_VALUE 0xFFFFFFFF
// Constant definitions
#define INDICATOR_NAME “ASCTrend-2TF”
#define INDICATOR_VERSION “1.01”
#define MATRIX_CHAR 110
#define IND_ASCTREND “ASCTrend1i”
#define MATRIX_ROWS 2 // Max rows in the Matrix
#define IDX_R1 0 // TF1
#define IDX_R2 1 // TF2
// Indicator parameters
extern string Indi.Version=INDICATOR_VERSION;
extern string TimeFrame.Settings=”——————————————————————————————”;
extern int TimeFrame1.Period=0; // Timeframe: 0,1,5,15,30,60,240,1440 etc. Current Timeframe=0.
extern int TimeFrame2.Period=0; // Timeframe: 0,1,5,15,30,60,240,1440 etc. Current Timeframe=0.
extern bool TimeFrame.Auto=True; // Automatically select higher TF for second line
extern string ASCTrend.Settings=”——————————————————————————————”;
extern int ASCTrend.Risk=6; // ASCTrend1 risk setting
extern string Alert.Settings=”——————————————————————————————”;
extern bool Alert.OnBarClose=True; // Alert only when an open bar closes
extern int Alert.MatrixLine=0; // Use the bar close of this line
extern bool Alert.Popup=False; // Enable popup window & sound on alert
extern string Alert.Sound=””; // Play sound on alert. Wav files only
extern bool Alert.Email=False; // Enable send email on alert
extern string Alert.Subject=””; // Email Subject. Null string (“”) will result in a preconfigured subject.
extern string Label.Settings=”——————————————————————————————”;
extern color Label.Color=White; // Color of Histogram Id labels
extern string PeriodDividerLine.Settings=”——————————————————————————————”;
extern int PDLine.Bars=1000;
extern color PDLine1.Color=White; // Color of the TF1 period divider line
extern int PDLine1.Style=STYLE_DOT; // Style of the TF1 period divider line: SOLID=0, DASH=1, DOT=2, DASHDOT=3, DASTDOTDOT=4
extern int PDLine1.Size=1; // Size of the TF1 period divider line. Set to 0 to not show the line.
extern color PDLine2.Color=Silver; // Color of the TF2 period divider line
extern int PDLine2.Style=STYLE_SOLID; // Style of the TF2 period divider line: SOLID=0, DASH=1, DOT=2, DASHDOT=3, DASTDOTDOT=4
extern int PDLine2.Size=1; // Size of the TF2 period divider line. Set to 0 to not show the line.
// Global module varables
// Histogram
double gadR1Up[];
double gadR1Dn[];
double gadR2Up[];
double gadR2Dn[];
// Labels
double gadGap[MATRIX_ROWS];
// Globals
int giRepaintBars[MATRIX_ROWS];
int giTimeFrame[MATRIX_ROWS];
string gsIndicatorName;
bool gbInit;
//—————————————————————————–
// function: init()
// Description: Custom indicator initialization function.
//—————————————————————————–
int init() {
// Init indicator buffers
IndicatorBuffers(4);
SetIndexStyle(0,DRAW_ARROW);
SetIndexBuffer(0,gadR1Up);
SetIndexStyle(1,DRAW_ARROW);
SetIndexBuffer(1,gadR1Dn);
SetIndexStyle(2,DRAW_ARROW);
SetIndexBuffer(2,gadR2Up);
SetIndexStyle(3,DRAW_ARROW);
SetIndexBuffer(3,gadR2Dn);
for (int i = 0; i < indicator_buffers; i++) {
SetIndexLabel(i,NULL);
SetIndexEmptyValue(i,0.0);
SetIndexArrow(i,MATRIX_CHAR);
}
// Set Timeframe
if (TimeFrame.Auto) {
giTimeFrame[IDX_R1]=Period();
giRepaintBars[IDX_R1]=0;
giTimeFrame[IDX_R2]=NextHigherTF(giTimeFrame[IDX_R1]);
giRepaintBars[IDX_R2]=giTimeFrame[IDX_R2]/Period()+2;
}
else {
giTimeFrame[IDX_R1]=TimeFrame1.Period;
giRepaintBars[IDX_R1]=giTimeFrame[IDX_R1]/Period()+2;
giTimeFrame[IDX_R2]=TimeFrame2.Period;
giRepaintBars[IDX_R2]=giTimeFrame[IDX_R2]/Period()+2;
}
// Set histogram positions
gadGap[IDX_R1]=0.7;
gadGap[IDX_R2]=0.2;
// Check that required indicators are installed
if (!IndicatorExists(IND_ASCTREND+”.ex4″))
Alert(Symbol()+”, “+TF2Str(Period())+”, “+INDICATOR_NAME+”: Error! “+TerminalPath()+”\\experts\\indicators\\”+IND_ASCTREND+”.ex4 cannot be found.”);
// Misc
gsIndicatorName=INDICATOR_NAME;
IndicatorShortName(gsIndicatorName);
gbInit=True;
return(0);
}
//—————————————————————————–
// function: deinit()
// Description: Custom indicator deinitialization function.
//—————————————————————————–
int deinit() {
// Clear text objects
for(int i=ObjectsTotal()-1; i>-1; i–)
if (StringFind(ObjectName(i),gsIndicatorName)>=0) ObjectDelete(ObjectName(i));
return (0);
}
//—————————————————————————–
// function: start()
// Description: Custom indicator iteration function.
//—————————————————————————–
int start() {
int i, j, iNewBars, iCountedBars, iDrawLines=0;
static datetime tCurBar;
// Get unprocessed bars
iCountedBars=IndicatorCounted();
if(iCountedBars < 0) return (-1);
if(iCountedBars>0) iCountedBars–;
// Timeframe 1
// Set bars to redraw
iNewBars=MathMax(RedrawBars(giTimeFrame[IDX_R1],IDX_R1,iCountedBars),giRepaintBars[IDX_R1]);
iDrawLines=MathMax(iDrawLines,iNewBars);
// Calc indicator data and update matrix
ProcessASCTrend(iNewBars, giTimeFrame[IDX_R1], ASCTrend.Risk, 0, gadR1Up, gadR1Dn,IDX_R1);
// Timeframe 2
// Set bars to redraw
iNewBars=MathMax(RedrawBars(giTimeFrame[IDX_R2],IDX_R2,iCountedBars),giRepaintBars[IDX_R2]);
iDrawLines=MathMax(iDrawLines,iNewBars);
// Calc indicator data and update matrix
ProcessASCTrend(iNewBars, giTimeFrame[IDX_R2], ASCTrend.Risk, 0, gadR2Up, gadR2Dn,IDX_R2);
// Alerts
CheckAlert();
// Tasks to execute on bar close
if (tCurBar!=Time[0] || iDrawLines>PDLine.Bars) {
tCurBar=Time[0];
// Write/Update bar labels
Writelabel(TF2Str(giTimeFrame[IDX_R1]),gadGap[IDX_R1]+0.2,Time[0]+Period()*60*2);
Writelabel(TF2Str(giTimeFrame[IDX_R2]),gadGap[IDX_R2]+0.2,Time[0]+Period()*60*2);
// Update time-frame divider lines
for (i=iNewBars;i>=0;i–) {
//PrintD(“Start”);
if (i>PDLine.Bars)
continue;
else if (iBarShift(Symbol(), giTimeFrame[IDX_R2], Time[i]) != iBarShift(Symbol(), giTimeFrame[IDX_R2], Time[i+1]) && PDLine2.Size>0)
DrawDividerLine(i,i,PDLine2.Style,PDLine2.Size,PDLine2.Color);
else if (iBarShift(Symbol(), giTimeFrame[IDX_R1], Time[i]) != iBarShift(Symbol(), giTimeFrame[IDX_R1], Time[i+1]) && PDLine1.Size>0 && giTimeFrame[IDX_R1]>Period())
DrawDividerLine(i,i,PDLine1.Style,PDLine1.Size,PDLine1.Color);
}
// Clear the init flag
if (gbInit)
gbInit=False;
}
return(0);
}
//—————————————————————————–
// function: RedrawBars()
// Description: Return nr of bars to draw/redraw bars on a TF
//—————————————————————————–
int RedrawBars(int iPeriod, int idx, int iCountedBars) {
static int iPrevSize[MATRIX_ROWS];
int iNewSize;
int iNewBars;
datetime tTimeArray[];
ArrayCopySeries(tTimeArray,MODE_TIME,Symbol(),iPeriod);
iNewSize=ArraySize(tTimeArray);
iNewBars=iNewSize-iPrevSize[idx];
iPrevSize[idx]=iNewSize;
if (iNewBars>0)
return(Bars-1);
//PrintD(“Idx=”+idx+”, Bars=”+iNewBars+”, Time=”+TimeToStr(Time[0]));
return(Bars-iCountedBars);
}
//—————————————————————————–
// function: ProcessTVI()
// Description: Calc TVI data and update matrix
//—————————————————————————–
int ProcessASCTrend(int iNewBars, int iTimeFrame, int iRisk, int iBarCount, double& vdUp[], double& vdDn[], int iRow) {
int i,j;
double dAscTrend;
int iHTFBar=-1;
for (i=iNewBars;i>=0;i–) {
// Get index for higher timeframe bar
if (iTimeFrame>Period())
j=iBarShift(Symbol(), iTimeFrame, Time[i], True);
else
j=i;
// Calc ASCTrend
if (iHTFBar!=j && j>=0) {
iHTFBar=j;
dAscTrend=iCustom(Symbol(),iTimeFrame,IND_ASCTREND,iRisk,iBarCount,2,j);
}
else if (j<0) {
dAscTrend=0;
}
// Bull signal
if (dAscTrend==1) {
vdUp[i]=gadGap[iRow];
vdDn[i]=0;
}
// Bear signal
else if (dAscTrend==-1) {
vdDn[i]=gadGap[iRow];
vdUp[i]=0;
}
else {
vdUp[i]=0;
vdDn[i]=0;
}
}
return(0);
}
//—————————————————————————–
// function: CheckAlert()
// Description: Check for new alerts
//—————————————————————————–
void CheckAlert() {
static datetime tAlertBar;
static int iPrevAlert=0;
if (Alert.Popup || Alert.Email || Alert.Sound!=””) {
// Alert on the close of the current bar
if (Alert.OnBarClose && tAlertBar<Time[iBarShift(Symbol(), giTimeFrame[Alert.MatrixLine], Time[0])]) {
tAlertBar=Time[iBarShift(Symbol(), giTimeFrame[Alert.MatrixLine], Time[0])];
// Clear alert flag
if (iPrevAlert==1 && !UpSignal(1))
iPrevAlert=0;
else if (iPrevAlert==-1 && !DnSignal(1))
iPrevAlert=0;
// Alert and set alert flag
if (UpSignal(1) && iPrevAlert!=1) {
AlertNow(Symbol()+”, “+TF2Str(giTimeFrame[Alert.MatrixLine])+”: ASCTrend1 Matrix Buy Signal.”);
iPrevAlert=1;
}
else if (DnSignal(1) && iPrevAlert!=-1) {
AlertNow(Symbol()+”, “+TF2Str(giTimeFrame[Alert.MatrixLine])+”: ASCTrend1 Matrix Sell Signal.”);
iPrevAlert=-1;
}
}
// Alert while the current bar is open
if (!Alert.OnBarClose && tAlertBar<Time[iBarShift(Symbol(), giTimeFrame[Alert.MatrixLine], Time[0])]) {
// Clear alert flag
if (iPrevAlert==1 && !UpSignal(0))
iPrevAlert=0;
else if (iPrevAlert==-1 && !DnSignal(0))
iPrevAlert=0;
// Alert and set alert flag
if (UpSignal(0) && iPrevAlert!=1) {
AlertNow(Symbol()+”, “+TF2Str(giTimeFrame[Alert.MatrixLine])+”: ASCTrend1 Matrix Buy Signal.”);
iPrevAlert=1;
tAlertBar=Time[iBarShift(Symbol(), giTimeFrame[Alert.MatrixLine], Time[0])];
}
else if (DnSignal(0) && iPrevAlert!=-1) {
AlertNow(Symbol()+”, “+TF2Str(giTimeFrame[Alert.MatrixLine])+”: ASCTrend1 Matrix Sell Signal.”);
iPrevAlert=-1;
tAlertBar=Time[iBarShift(Symbol(), giTimeFrame[Alert.MatrixLine], Time[0])];
}
}
}
return;
}
//—————————————————————————–
// function: AlertNow()
// Description: Signal the popup and email alerts
//—————————————————————————–
void AlertNow(string sAlertMsg) {
//Popup Alert
if (Alert.Popup)
Alert(INDICATOR_NAME, “, “, sAlertMsg);
if (Alert.Sound!=””)
PlaySound(Alert.Sound);
//Email Alert
if (Alert.Email) {
if (Alert.Subject==””)
SendMail( sAlertMsg, “MT4 Alert!\n”+INDICATOR_NAME+”\n” + TimeToStr(Time[0],TIME_DATE|TIME_SECONDS )+”\n”+sAlertMsg);
else
SendMail( Alert.Subject, “MT4 Alert!\n”+INDICATOR_NAME+”\n” + TimeToStr(Time[0],TIME_DATE|TIME_SECONDS )+”\n”+sAlertMsg);
}
return;
}
//—————————————————————————–
// function: UpSignal()
// Description: Return true if there is an up signal
//—————————————————————————–
bool UpSignal(int i) {
if (gadR1Up[i]>0 && gadR2Up[i]>0)
return(True);
else
return(False);
}
//—————————————————————————–
// function: DnSignal()
// Description: eturn true if there is a down signal
//—————————————————————————–
bool DnSignal(int i) {
if (gadR1Dn[i]>0 && gadR2Dn[i]>0)
return(True);
else
return(False);
}
//—————————————————————————–
// function: Writelabel()
// Description: Write a label for a bar
//—————————————————————————–
int Writelabel(string sLabel,double dPrice, datetime tTime) {
string sObjId;
sObjId=gsIndicatorName+”_”+sLabel;
if(ObjectFind(sObjId) < 0)
ObjectCreate(sObjId, OBJ_TEXT, WindowFind(gsIndicatorName), tTime+Period()*60*2, dPrice);
ObjectSetText(sObjId, sLabel, 6, “Lucida Console”, Label.Color);
ObjectMove(sObjId,0,tTime, dPrice);
return(0);
}
//—————————————————————————–
// function: DrawDividerLine()
// Description: Draw a horizontal divider line to show when a new bar starts
//—————————————————————————–
int DrawDividerLine(int iBar, int iLineNr, int iLineStyle=STYLE_SOLID, int iLineWidth=1, color cLineColor=White) {
string sLineId;
// Set Line object ID
sLineId=gsIndicatorName+”_Divider_”+iLineNr;
// Delete line if it exists
if (ObjectFind(sLineId)>=0 )
ObjectDelete(sLineId);
// Create and Draw line
ObjectCreate(sLineId, OBJ_TREND, WindowFind(gsIndicatorName), Time[iBar], -90, Time[iBar+1], 80);
ObjectSet(sLineId, OBJPROP_STYLE, iLineStyle);
ObjectSet(sLineId, OBJPROP_WIDTH, iLineWidth);
ObjectSet(sLineId, OBJPROP_BACK, False);
ObjectSet(sLineId, OBJPROP_COLOR, cLineColor);
ObjectSet(sLineId, OBJPROP_RAY, False);
ObjectSet(sLineId, OBJPROP_TIME1, Time[iBar]);
ObjectSet(sLineId, OBJPROP_TIME2, Time[iBar+1]);
return(0);
}
//—————————————————————————–
// function: IndicatorExists()
// Description: Check if an indicator exists
//—————————————————————————–
bool IndicatorExists(string sIndicatorName) {
int hFile;
string sFile;
// Exit if dlls are disabled
if (!IsDllsAllowed())
return(True);
// Try to open indicator
sFile=TerminalPath()+”\\experts\\indicators\\”+sIndicatorName;
hFile=CreateFileA(sFile,0,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if (hFile==INVALID_HANDLE_VALUE) {
return(False);
}
else {
CloseHandle(hFile);
return(True);
}
return(False);
}
//—————————————————————————–
// function: TF2Str()
// Description: Convert time-frame to a string
//—————————————————————————–
string TF2Str(int iPeriod) {
switch(iPeriod) {
case PERIOD_M1: return(“M1”);
case PERIOD_M5: return(“M5”);
case PERIOD_M15: return(“M15”);
case PERIOD_M30: return(“M30”);
case PERIOD_H1: return(“H1”);
case PERIOD_H4: return(“H4”);
case PERIOD_D1: return(“D1”);
case PERIOD_W1: return(“W1”);
case PERIOD_MN1: return(“MN1”);
default: return(“M”+iPeriod);
}
return(0);
}
//—————————————————————————–
// function: NextHigherTF()
// Description: Select the next higher time-frame.
// Note: M15 and M30 both select H1 as next higher TF.
//—————————————————————————–
int NextHigherTF(int iPeriod) {
if (iPeriod==0) iPeriod=Period();
switch(iPeriod) {
case PERIOD_M1: return(PERIOD_M5);
case PERIOD_M5: return(PERIOD_M15);
case PERIOD_M15: return(PERIOD_H1);
case PERIOD_M30: return(PERIOD_H1);
case PERIOD_H1: return(PERIOD_H4);
case PERIOD_H4: return(PERIOD_D1);
case PERIOD_D1: return(PERIOD_W1);
case PERIOD_W1: return(PERIOD_MN1);
case PERIOD_MN1: return(PERIOD_MN1);
default: return(Period());
}
return(Period());
}