This script is an automated trading program designed to work with the MetaTrader platform. Its primary goal is to automatically open and close trading positions (buy or sell) based on analysis of the price charts. Here's a breakdown of what the script does, in plain language:
1. Setup & Initialization:
- Configuration: The script starts by setting up several customizable parameters. These include the size of trades it will make ("Lots"), how much price fluctuation it will tolerate ("Slippage"), a comment to identify its trades ("Order_Comment"), and various settings related to technical indicators.
- Currency Pair Configuration: The script allows configuring the SSP and SSK for different pairs based on an array of configured pairs
- Data Storage: It also sets up some internal storage to keep track of things like the last time a new price bar appeared on the chart, what the overall trend is, and a unique identifier ("Magic Number") to distinguish its trades from others.
- Logging: It also initializes a file to log trade activities
2. Core Logic (The start()
function):
- Checking for New Data: The script constantly monitors the price chart. It only takes action when a new price "bar" (representing a specific time period like an hour or a day) appears, ensuring it's working with the most up-to-date information.
- Trend Detection: The core of the script is determining whether the price is trending upwards (suggesting a buying opportunity), downwards (suggesting a selling opportunity), or sideways (suggesting no clear opportunity). It uses several technical indicators to make this determination:
- Ichimoku Cloud: This is a complex indicator that uses multiple lines to define support and resistance levels and overall trend direction. The script uses these lines to assess whether the current price is above or below the "cloud," which is interpreted as a buy or sell signal.
- Moving Averages: The script compares two moving averages (one calculated over a shorter period, one over a longer period). If the shorter-term average is above the longer-term average, it suggests an upward trend; if it's below, a downward trend.
- Parabolic SAR (PSAR): This indicator places dots on the chart to suggest potential reversals in price direction. The script monitors the PSAR to confirm trends.
- Relative Strength Index (RSI): The script takes into account the RSI indicator
- Order Management:
- Closing Existing Trades: If the script already has an open trade, it checks if the trend has changed. If the trend has reversed (e.g., it's in a buy trade but now sees a sell signal), it closes the existing trade to capture profits or minimize losses.
- Opening New Trades: If the script has no open trades, it checks the trend. If it sees a clear buy or sell signal (based on its indicator analysis), it opens a new trade in the appropriate direction. A trade is only open if the Ichiomoku signal is confirmed with the moving averages signal
- Logging: The script records information about its trading decisions (buy, sell, close, profits, etc.) in a log file. This helps track performance and troubleshoot any issues.
- Information Display: The script can optionally display information about the current price, indicators, and order status on the chart itself.
3. Technical Indicators:
- Ichimoku Cloud Calculation: The script includes a function (
AIchimoku()
) to calculate the various lines that make up the Ichimoku Cloud indicator. It looks at the highest and lowest prices over specific periods to determine these levels.
In summary: This script is an automated trading system that uses a combination of technical indicators (primarily the Ichimoku Cloud, Moving Averages, PSAR and RSI) to identify potential buying and selling opportunities. It automatically opens and closes trades based on these signals, while also managing risk and logging its activity.
//+------------------------------------------------------------------+
//| simplefx.mq4 |
//| Copyright © 2007, GLENNBACON.COM LLC |
//| http://www.GetForexSoftware.com |
//+------------------------------------------------------------------+
// Shift of moving average
#define Shift 1
// Trend Detection function
#define TREND_BUY 11
#define TREND_SELL 22
#define TREND_CLOSE 33
//parametros Medias moveis
int Long_MA_Period = 200;
int Long_MA_Method = 0;
int Long_MA_Applied_Price = 4;
int Short_MA_Period = 50;
int Short_MA_Method = 0;
int Short_MA_Applied_Price = 4;
#define MABULL 111111
#define MABEAR 222222
// Input variables
extern double Lots = 0.30;
extern int Slippage = 3;
extern string Order_Comment = "EL FODEURO";
extern color Order_Arrow_Color = Green;
extern double PercentMargin = 0.005;
extern int NOGOVolatility = 200;
extern int SMALLGOVolatility = 100;
extern int SSP = 34; // bars - calculating period
extern int SSK = 29; // tolerance of second line
// Global variables
int Total_Open_Orders = 1; // we only want to open one order at a time and only manage the one order
int cnt = 0; // counter variable, used in for() loops
bool init_variables; // init variable when program starts
datetime PreviousBar; // record the candle/bar time
int NowTrend = TREND_CLOSE;
int Magic = 1;
string pairs[9] ;
int SSPS[9] ;
int SSKS[9];
int logHandler;
string logFileName;
double profits[1];
int profitIdx = 1;
int lastSARTrend;
//Indicators
double ExtMapBuffer1[];
double ExtMapBuffer2[];
double Wal1[];
double Wal2[];
double ExtMapBuffer4[];
int i, i1, i2, shift;
double SsMax, SsMin, SsMax05, SsMin05, Rsmin, Rsmax, Tsmin, Tsmax;
int val1, val2, AvgRange;
bool uptrend, old;
double iClose0,iClose1,iIchi,iLine1,iLine2;
int init()
{
init_variables = true; // Allows us to init variables in the start function because
// we cannot do this in the init function because the variables
// use values from the chart ~
logFileName = StringConcatenate( Symbol() , ".log") ;
pairs[0] = "EURUSD";
pairs[1] = "GBPCHF";
pairs[2] = "EURJPY";
pairs[3] = "USDJPY";
pairs[4] = "GBPUSD";
pairs[5] = "EURGBP";
pairs[6] = "CADCHF";
pairs[7] = "GBPJPY";
pairs[8] = "EURCHF";
/*
Pair Time SSP SSK
CADJPY 4H 48 36
EURCHF 4H 72 50
USDCAD 4H 24 60
USDCHF 4H 34 29
*/
SSPS[8] = 72;
SSKS[8] =50;
SSPS[7] = 36;
SSKS[7] =29;
SSPS[6] = 62;
SSKS[6] =52;
SSPS[5] = 44;
SSKS[5] =38;
SSPS[0] = 34;
SSKS[0] =34;
SSPS[0] = 34;
SSKS[0] =34;
SSPS[1] = 34;
SSKS[1] =29;
SSPS[2] = 36;
SSKS[2] =29;
SSPS[3] = 34;
SSKS[3] =29;
SSPS[4] = 44;
SSKS[4] =36;
int i;
for(i=0;i<ArraySize(pairs) ;i++ ) {
if ( pairs[i] == Symbol() ) {
SSP = SSPS[i];
SSK = SSKS[i];
Print("SSP=", SSP);
Print("SSK=",SSK);
break;
}
}
/*
Pair Time SSP SSK
EURGBP 4H 44 38
CADCHF 4H 62 52
CADJPY 4H 48 36
GBPUSD 4H 44 36
GBPCHF 4H 34 29
GBPJPY 4H 36 29
EURUSD 4H 34 34
EURCHF 4H 72 50
EURJPY 4H 72 36
USDCAD 4H 24 60
USDCHF 4H 34 29
USDJPY 4H 34 29
*/
Magic = createMagicNumber();
return(0);
}
int deinit()
{
// clear chart when EA is removed
ObjectsDeleteAll();
return(0);
}
int start()
{
logHandler=FileOpen(logFileName, FILE_CSV | FILE_READ | FILE_WRITE , ';');
FileSeek(logHandler, 0, SEEK_END);
if(logHandler<1)
{
Print("file error the last error is ", GetLastError());
return (false);
}
// make sure trader has set Lots to at least the minimum lot size of the broker and
// we will normalize the Lots variable so we can properly open an order
if(MarketInfo(Symbol(),MODE_MINLOT) == 0.01)
{
Lots = NormalizeDouble(Lots,2);
if(Lots < 0.01)
{
Comment("The variable Lots must be 0.01 or greater to open an order. ");
return(0);
}
}
if(MarketInfo(Symbol(),MODE_MINLOT) == 0.1)
{
Lots = NormalizeDouble(Lots,1);
if(Lots < 0.1)
{
Comment("The variable Lots must be 0.1 or greater to open an order. ");
return(0);
}
}
if(MarketInfo(Symbol(),MODE_MINLOT) == 1)
{
Lots = NormalizeDouble(Lots,0);
if(Lots < 1)
{
Comment("The variable Lots must be 1 or greater to open an order. ");
return(0);
}
}
// init variables when the expert advisor first starts running
if(init_variables == true)
{
PreviousBar = Time[0]; // record the current canle/bar open time
// place code here that you only wnat to run one time
MathSrand(TimeLocal());
init_variables = false; // change to false so we only init variable once
// Magic = MathRand();
}
// perform analysis and open orders on new candle/bar
if(NewBar() == true)
{
NowTrend = TrendDetection();
int MATrend = MATrend();
int SARTrend = getPSarTrend();
int RSITrend = getRSITrend();
string rsi = StringConcatenate(iRSI(NULL,0,14,PRICE_CLOSE,0),";",iRSI(NULL,0,14,PRICE_CLOSE,1));
// only perform analysis and close order if we only have one order open
if(TotalOpenOrders() == Total_Open_Orders && SelectTheOrder() == true)
{
StoreCurrentProfit();
logInfo(logHandler,getProfitAsString(OrderTicket(),OrderProfit(), RSITrend,MATrend,SARTrend,rsi));
if((OrderType()) == OP_BUY && ((NowTrend == TREND_SELL) || (NowTrend == TREND_CLOSE)))
{
logInfo(logHandler,StringConcatenate("SAIDA",";",Symbol(),";",OrderTicket(),";",OrderProfit(),";",TimeLocal()));
OrderClose(OrderTicket(),OrderLots(),Bid,Slippage,Order_Arrow_Color);
}
if((OrderType() == OP_SELL) && ((NowTrend == TREND_BUY) || (NowTrend == TREND_CLOSE)))
{
logInfo(logHandler,StringConcatenate("SAIDA",";",Symbol(),";",OrderTicket(),";",OrderProfit(),";",TimeLocal()));
//logInfo(logHandler,getProfitAsString(OrderTicket(),OrderProfit(), RSITrend,MATrend,SARTrend,rsi));
OrderClose(OrderTicket(),OrderLots(),Ask,Slippage,Order_Arrow_Color);
}
}
// only perform analysis and open new order if we have not reached our Total_Open_Orders max
if(TotalOpenOrders() < Total_Open_Orders)
{
int tickOrder ;
// open buy
if(NowTrend == TREND_BUY)
{
// open order
if ( MATrend == MABULL) {
tickOrder = OrderSend(Symbol(),OP_BUY,Lots,Ask,Slippage,0,0,Order_Comment,Magic,0,Order_Arrow_Color);
if(tickOrder<0)
{
Print("OrderSend failed with error #",GetLastError());
return(0);
}
Print("Comprei " , Symbol() , " ticket ", tickOrder);
PlaySound("alert2.wav");
logInfo(logHandler,StringConcatenate("Compra",";",Symbol(),";",tickOrder,";",rsi,";",SARTrend,";",TimeLocal()));
Print(" SAR TREND compra " , SARTrend);
Print(" RSI TREND compra " , RSITrend);
}
else {
Print(" O Sinal do ichimoku nao foi confirmado pela MA na compra" );
}
}
// open sell
if(NowTrend == TREND_SELL)
{
// open order
if ( MATrend== MABEAR) {
tickOrder = OrderSend(Symbol(),OP_SELL,Lots,Bid,Slippage,0,0,Order_Comment,Magic,0,Order_Arrow_Color);
if(tickOrder<0)
{
Print("OrderSend failed with error #",GetLastError());
return(0);
}
Print("Vendi " , Symbol(), " ticket ", tickOrder);
PlaySound("alert2.wav");
logInfo(logHandler,StringConcatenate("VENDA",";",Symbol(),";",tickOrder,";",rsi,";",SARTrend,";",TimeLocal()));
Print(" SAR TREND venda " , SARTrend);
Print(" RSI TREND venda " , RSITrend);
//Print(" O indicador MA esta a confirmar o sinal do ichimoku na venda " );
}
else {
Print(" O Sinal do ichimoky nao foi confirmado pela MA na venda " );
}
}
}
/*
Print("Date: ",Month(),"-",Day(),"-",Year()," Server Time: ",Hour(),":",Minute(),":",Seconds(),
" volatility:", AvgRange,
" iClose0: ",iClose0,
" iClose1: ",iClose1,
" iIchi: ",iIchi,
" iLine1: ",iLine1,
" iLine2: ",iLine2,
" Trend: ",NowTrend);
*/
Display_Info();
}
lastSARTrend = SARTrend;
FileClose(logHandler);
return(0);
}
/////////////////////////////////////////////////////////////////////////
// Common functions //
///////////////////////////////////////////////////////////////////////
void StoreCurrentProfit() {
profits[profitIdx-1] = OrderProfit();
profitIdx++;
ArrayResize(profits,profitIdx);
}
string getProfitAsString(int orderTicket ,double profit , int matrend,int rsitrend, int sartrend,string rsi ) {
return (StringConcatenate("PROFIT;", orderTicket, ";" ,Symbol(), ";",profit, ";", matrend,";",rsitrend,";",sartrend,";",rsi,";",TimeLocal()));
}
void logInfo(int handle, string value) {
//Print(" handle ", handle);
Print( value);
FileWrite(handle,value);
}
// This function returns the total amount of orders the expert advisor has open
int TotalOpenOrders()
{
cnt=OrdersTotal();
int TotalOpenOrders = 0;
if(cnt==0)
{
return(0);
}
else
{
for(;cnt>=0;cnt--)
{
RefreshRates();
OrderSelect(cnt,SELECT_BY_POS);
if(OrderMagicNumber()==Magic)
{
TotalOpenOrders++;
}
}
}
return(TotalOpenOrders);
}
// This function finds the open order and selects it
int SelectTheOrder()
{
cnt=OrdersTotal();
if(cnt==0)
{
return(false);
}
else
{
for(;cnt>=0;cnt--)
{
RefreshRates();
OrderSelect(cnt,SELECT_BY_POS);
if(OrderMagicNumber()==Magic)
{
return(true);
}
}
}
return(false);
}
// This function return the value true if the current bar/candle was just formed
bool NewBar()
{
if(PreviousBar<Time[0])
{
PreviousBar = Time[0];
return(true);
}
else
{
return(false);
}
return(false); // in case if - else statement is not executed
}
// is trend up/bullish or is it down/bearish
int TrendDetection()
{
double topLine,bottomLine;
if (iClose1 == 0)
iClose1 = iClose(NULL,0,10);
else
iClose1 = iClose0;
iClose0 = iClose(NULL,0,0);
AIchimoku();
if (iLine1 > iLine2)
{
topLine = iLine1;
bottomLine = iLine2;
}
else
{
topLine = iLine2;
bottomLine = iLine1;
}
if ((iClose0 > iIchi) && (iClose1 < iIchi))
return(TREND_BUY);
if ((iClose0 < iIchi) && (iClose1 > iIchi))
return(TREND_SELL);
if ((iClose0 < topLine ) && (iClose0 > bottomLine))
return(TREND_CLOSE);
if (AvgRange < NOGOVolatility )
{
if ((iClose0 > topLine) && (iClose0 > iClose1))
if (((iClose0-topLine)/iClose0)<PercentMargin)
return(TREND_BUY);
if ((iClose0 < bottomLine) && (iClose0 < iClose1))
if (((bottomLine-iClose0)/bottomLine)<PercentMargin)
return(TREND_SELL);
}
// flat no trend return 0
return(0);
}
int MATrend()
{
// BULL trend
if(iMA(NULL,0,Short_MA_Period,0,Short_MA_Method,Short_MA_Applied_Price,0) > iMA(NULL,0,Long_MA_Period,0,Long_MA_Method,Long_MA_Applied_Price,0) && iMA(NULL,0,Short_MA_Period,0,Short_MA_Method,Short_MA_Applied_Price,1) > iMA(NULL,0,Long_MA_Period,0,Long_MA_Method,Long_MA_Applied_Price,1))
{
return(MABULL);
}
// BEAR trend
if(iMA(NULL,0,Short_MA_Period,0,Short_MA_Method,Short_MA_Applied_Price,0) < iMA(NULL,0,Long_MA_Period,0,Long_MA_Method,Long_MA_Applied_Price,0) && iMA(NULL,0,Short_MA_Period,0,Short_MA_Method,Short_MA_Applied_Price,1) < iMA(NULL,0,Long_MA_Period,0,Long_MA_Method,Long_MA_Applied_Price,1))
{
return(MABEAR);
}
// flat no trend return 0
return(0);
}
void Display_Info()
{
Comment("Price: ",NormalizeDouble(Bid,4),"\n",
"Date: ",Month(),"-",Day(),"-",Year()," Server Time: ",Hour(),":",Minute(),":",Seconds(),"\n",
"volatility: ", AvgRange,"\n",
"iClose0: ",DoubleToStr(iClose0,4),"\n",
"iClose1: ",DoubleToStr(iClose1,4),"\n",
"iIchi: ",DoubleToStr(iIchi,4),"\n",
"iLine1: ",DoubleToStr(iLine1,4),"\n",
"iLine2: ",DoubleToStr(iLine2,4),"\n",
"TotalOrders : ",TotalOpenOrders(),"\n");
return(0);
}
bool CheckIfOrderExists(string symbol, int orderType ) {
cnt=OrdersTotal();
if(cnt==0)
{
return(false);
}
else
{
for(;cnt>=0;cnt--)
{
RefreshRates();
OrderSelect(cnt,SELECT_BY_POS);
Print ( OrderSymbol(), " ",OrderMagicNumber(), " ", Magic);
if ( OrderSymbol() == symbol && OrderType() == orderType ) return (true);
}
}
return(false);
}
int getPSarTrend() {
if(iSAR(NULL,0,0.02,0.2,1)<Low[1] && iSAR(NULL,0,0.02,0.2,0)>High[0])
{
return (TREND_SELL);
}
if(iSAR(NULL,0,0.02,0.2,1)>High[1] && iSAR(NULL,0,0.02,0.2,0)<Low[0])
{
return (TREND_BUY);
}
else return(0);
}
int getRSITrend() {
double RSI[8]; // 6
double EMA, EMA1;
double RSI1[8];
ArraySetAsSeries(RSI, true); // 1
for (int x=0; x<=7;x++)
{
RSI[x]=iRSI(NULL,0,8,PRICE_CLOSE,x);
}
EMA=iMAOnArray(RSI,0,8,0,MODE_EMA,0); // 2
for (x=1; x<=8;x++)
{
RSI1[x]=iRSI(NULL,0,8,PRICE_CLOSE,x);
}
EMA1=iMAOnArray(RSI1,0,8,0,MODE_EMA,1); // 2
if (EMA<RSI[0] && EMA1>RSI[0]) return(TREND_BUY);
else if (EMA>RSI[0] && EMA1<RSI[0] ) return(TREND_SELL) ;
else return (0);
}
int createMagicNumber() {
string symbol = Symbol();
int t = 0 ;
for(int i=0;i<StringLen(symbol);i++) {
t += StringGetChar(symbol,i);
}
return (t);
}
void AIchimoku()
{
// maximum of previous SSP bars period
SsMax = High[iHighest(NULL, 0, MODE_HIGH, SSP, 0)];
// minimum of previous SSP bars period
SsMin = Low[iLowest(NULL, 0, MODE_LOW, SSP, 0)];
// maximum of SSP bars period for SSK bars from begin
SsMax05 = High[iHighest(NULL, 0, MODE_HIGH, SSP, 0 + SSK)];
// maximum of SSP bars period for SSK bars from begin
SsMin05 = Low[iLowest(NULL, 0, MODE_LOW, SSP, 0 + SSK)];
iLine1 = (SsMax + SsMin) / 2;
iLine2 = (SsMax05+SsMin05) / 2;
val1 = ExtMapBuffer1[1] / Point;
val2 = ExtMapBuffer2[1] / Point;
//----
Rsmax = High[iHighest(NULL, 0, MODE_HIGH, SSP*2, 0)];
Rsmin = Low[iLowest(NULL, 0, MODE_LOW, SSP*2, 0)];
AvgRange = (Rsmax / Point) - (Rsmin / Point);
//----
Tsmax = High[iHighest(NULL, 0, MODE_HIGH, SSP*1.62, 0)];
Tsmin = Low[iLowest(NULL, 0, MODE_LOW, SSP*1.62, 0)];
iIchi = (Tsmax + Tsmin) / 2;
}
Comments