Je vous propose de tester cet EA au nom bizarre... :)
J'ai réglé cette version.
On en reparle avec des résultats de tests ?
---------------------------------------------------------------------------------------------------
/*
+------------------------------------------------------------------+
| FunYooSalad v1.0.mq4 (was vForce Like EA v3.mq4) |
| portions Copyright © 2009, TradingSytemForex |
| http://www.tradingsystemforex.com |
| Additions by Furax pour forexagone.com le 04 Novembre 2011 | |
| Additions by Maxim Feinshtein [email protected] |
| Additions by William House [email protected] |
| you can modify this expert |
| you can change the name |
| you can add "modified by you", |
| but you are not allowed to erase the copyrights |
+------------------------------------------------------------------+
*/
#define EAName "FunYooSalad v1.0"
#property copyright "Copyright © 2009, TradingSytemForex"
#property link "http://www.tradingsystemforex.com"
#include <WinUser32.mqh>
#include <stderror.mqh>
#define STANDARD_LOT_SIZE 100000.0
// Used for souble values comparisons
#define EPSILON 0.00001
#define TRADING_STATE_WAITING 0
#define TRADING_STATE_TRADING 1
// funyoo, why don't we use GMT offset?
extern string S1 = "--- Stochastic filter settings";
extern int StochKPeriod = 5;
extern int StochDPeriod = 3;
extern int StochSlowing = 3;
extern string S2 = "--- RSI indicator settings";
extern int RSIPeriod = 8; // was 2 !...
extern string S3 = "--- Bears power indicator settings";
extern int BearsPeriod = 12;
extern string S4 = "--- Moving average indicator settings";
extern int FastMAPeriod = 19;
extern int SlowMAPeriod = 50;
extern string S5 = "--- Parabolic stop and reverse system settings";
extern double PSARStep = 0.003;
extern double PSARMaximum = 0.018;
extern string S6 = "--- Money management settings";
extern bool MMEnabled = false; // Flag, indicating whether risk management is enabled.
extern double Lots = 0.1; // Lots size
extern double LotsPercent1 = 80; // First order percent
extern double LotsPercent2 = 20; // Second order percent
extern double RiskPercent = 1; // The risk percentage
extern double MinLots = 0.01; // Minimal lots
extern double MaxLots = 1; // Maximal lots
extern bool PriceFilterEnabled = false;
extern string S7 = "--- Order Management";
// The maximal trading spread for the cuurency pair
extern double MaximalSpread = 5.0;
// funyoo, what does this parameter mean?
extern int MarginPips = 23;
// The default stop loss (PIPs)
extern int StopLoss = 69;
// The default take profit (PIPs)
extern int TakeProfit = 24; // was 24
// Maximal number of concurrent orders
extern int MaxOrders = 3; // was 8
// Maximal acceptable slippage
extern int Slippage = 3;
// The ID of the first order
extern int Magic1 = 20091;
// The ID of the second order
extern int Magic2 = 20092;
// Average true range trailing stop time frame
extern int ATRTSTimeFrame = 1;
// Average true range trailing stop period
extern int ATRTSPeriod = 14;
// Average true range trailing stop factor
extern double ATRTSFactor = 7;
extern string S8 = "--- Time filter settings";
// Flag, indicating whether to trade on sunday
extern bool TradeOnSunday = true;
// Flag, indicating whether to trade only at hours,
// specified for monday through thursday trading.
// It actually tells whether monday to thursday time
// filtering is enabled.
extern bool MondayToThursdayTFEnabled = false;
// The start hour for monday through thursday trading.
extern int MondayToThursdayStartHour = 0;
// The end hour for monday through thursday trading.
extern int MondayToThursdayEndHour = 24;
// Flag, indicating whether to trade on friday
extern bool TradeOnFriday = true;
// The start hour for friday trading.
extern int FridayStartHour = 0;
// The end hour for friday trading.
extern int FridayEndHour = 21;
// Flag, indicating whether to close open trades
// when in non-trade hours (outside the time filter)
extern bool CloseOrdersInNonTradeHours = false;
extern string S9 = "--- Graphics settings";
extern color InformationColor = LightGreen;
extern int FontSize = 12;
extern string S10 = "--- Miscellaneous settings";
// Expiration in minutes for the reverse pending order,
// causes the ERR_TRADE_EXPIRATION_DENIED error.
// funyoo, when is it needed?
// Buy instead of sell, sell instead of buy
extern bool ReverseSystem = true; // was false
// funyoo, this caues oder send error,
// can you please refine the implementation?
extern int Expiration = 1; // was 0
// Graphical entities names.
string g_labelEAName = "labelEAName",
g_labelSpreadCaption = "labelSpreadCaption",
g_labelSpreadStatus = "labelSpreadStatus",
g_labelTradingState = "labelTradingState";
string g_fontName = "Times New Roman";
string g_BuySellState = "";
datetime g_PreviousBarTime1;
datetime g_PreviousBarTime2;
// Long and short arrows colors
color g_colorLong = Blue,
g_colorShort = Orange; // was Red
// Either Lots, specified by user or calclated
// according to risk settings
double g_tradingLots;
double g_order1Size,
g_order2Size;
// Fix for 5-digit brokers
int g_digits;
double g_point;
// Minimal and maximal spreads during
// treading session.
double g_currentSpread,
g_minSpread,
g_maxSpread;
// Controls how far or near are text lines on Y axis.
double g_textDensingFactor = 1.5;
// Either TRADING_STATE_WAITING or TRADING_STATE_TRADING
int g_tradingState = TRADING_STATE_WAITING;
// The offset of the first expert status string in pixels.
int g_baseXOffset = 15,
g_baseYOffset = 20;
// Last order Bar Id - -1 means no last order
int g_lastBuyOrderBarId = -1;
int g_lastSellOrderBarId = -1;
// The expert initialization function
int init()
{
initGraphics();
g_currentSpread = MarketInfo( Symbol(), MODE_SPREAD );
g_minSpread = g_currentSpread;
g_maxSpread = g_currentSpread;
g_PreviousBarTime1 = D'2004.01.01 00:00';
g_PreviousBarTime2 = D'2004.01.01 00:00';
g_point = GetPoints();
g_lastBuyOrderBarId = -1;
g_lastSellOrderBarId = -1;
updateSpreadInfo();
displayStatus();
return (0);
}
double GetPoints()
{
if(Digits==3 || Digits==5)g_point=Point*10;
else g_point=Point;
return(g_point);
}
// The expert uninitialization function
int deinit()
{
deinitGraphics();
return (0);
}
int start()
{
// Update trailing stop
if( ATRTSPeriod > 0 )
updateTrailingStopLosses();
updateSpreadInfo();
// Do time filtering
doTimeFiltering();
displayStatus();
if( TRADING_STATE_TRADING == g_tradingState )
{
doTradingLogic();
}
else if( CloseOrdersInNonTradeHours )
{
closeBuyOrders( Magic1 );
closeBuyOrders( Magic2 );
closeSellOrders( Magic1 );
closeSellOrders( Magic2 );
}
return (0);
}
// Initializes graphical objects
void initGraphics()
{
// Added to the main chart window.
ObjectCreate( g_labelEAName, OBJ_LABEL, 0, 0, 0 );
ObjectCreate( g_labelSpreadCaption, OBJ_LABEL, 0, 0, 0 );
ObjectCreate( g_labelSpreadStatus, OBJ_LABEL, 0, 0, 0 );
ObjectCreate( g_labelTradingState, OBJ_LABEL, 0, 0, 0 );
// Bind to top left corner
ObjectSet( g_labelEAName, OBJPROP_CORNER, 0 );
ObjectSet( g_labelSpreadCaption, OBJPROP_CORNER, 0 );
ObjectSet( g_labelSpreadStatus, OBJPROP_CORNER, 0 );
ObjectSet( g_labelTradingState, OBJPROP_CORNER, 0 );
// Set EA name cordinates
ObjectSet( g_labelEAName, OBJPROP_XDISTANCE, g_baseXOffset );
ObjectSet( g_labelEAName, OBJPROP_YDISTANCE, g_baseYOffset );
// Set spread caption X cordinate;
// the Y coordinate is calculated since depends on font size.
ObjectSet( g_labelSpreadCaption, OBJPROP_XDISTANCE, g_baseXOffset );
// Set spread status X cordinate;
// the Y coordinate is calculated since depends on font size.
ObjectSet( g_labelSpreadStatus, OBJPROP_XDISTANCE, g_baseXOffset );
// Set trading status X cordinate;
// the Y coordinate is calculated since depends on font size.
ObjectSet( g_labelTradingState, OBJPROP_XDISTANCE, g_baseXOffset );
}
// Releases used graphical objects
void deinitGraphics()
{
// Release used graphics resources
ObjectDelete( g_labelEAName );
ObjectDelete( g_labelSpreadCaption );
ObjectDelete( g_labelSpreadStatus );
ObjectDelete( g_labelTradingState );
}
// Performs trading logic
void doTradingLogic()
{
// Check whether it is possible to open more orders
int openedOrdersCount = calculateOpenedOrdersCount();
if( openedOrdersCount >= MaxOrders )
{
Print( "Maximal number of orders is already opened..." );
return;
}
string instrument = Symbol();
// Check whether current spread exceeds maximal allowed spread
double currentSpread = MarketInfo( instrument, MODE_SPREAD );
if( currentSpread > MaximalSpread )
{
Print(
"Current spread ",
NormalizeDouble( currentSpread, 1 ),
"exceeds maximal allowed spread ",
MaximalSpread
);
return;
}
// funyoo: why to use constant value?
int barID = 1;
// for( int i = 1; i <= limit; i++ )
// {
// Check for trade signal
// Retrieve 'stochastic oscillator' values
double StoMa = iStochastic( instrument, 0, StochKPeriod, StochDPeriod, StochSlowing, MODE_SMA, 0, MODE_MAIN, barID + 1 );
double StoM = iStochastic( instrument, 0, StochKPeriod, StochDPeriod, StochSlowing, MODE_SMA, 0, MODE_MAIN, barID );
double StoSa = iStochastic( instrument, 0, StochKPeriod, StochDPeriod, StochSlowing, MODE_SMA, 0, MODE_SIGNAL, barID + 1 );
double StoS = iStochastic( instrument, 0, StochKPeriod, StochDPeriod, StochSlowing, MODE_SMA, 0, MODE_SIGNAL, barID );
// Retrieve 'relative strength index' values
double RSIa = iRSI( instrument, 0, RSIPeriod, PRICE_CLOSE, barID + 1 );
double RSI = iRSI( instrument, 0, RSIPeriod, PRICE_CLOSE, barID );
// Retrieve 'bears power indicator' values
double Bearsa = iBearsPower( instrument, 0, BearsPeriod, PRICE_CLOSE, barID + 1 );
double Bears = iBearsPower( instrument, 0, BearsPeriod, PRICE_CLOSE, barID );
// Retrieve 'parabolic stop and reverse system' values
double SARa = iSAR( instrument, 0, PSARStep, PSARMaximum, barID + 1 );
double SAR = iSAR( instrument, 0, PSARStep, PSARMaximum, barID );
// Retrieve 'moving average' indicator svalues.
double imaFastCurrent = iMA( instrument, 0, FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE, barID ),
imaSlowPrevious = iMA( instrument, 0, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE, barID + 1 );
bool buySignalExists = false,
sellSignalExists = false;
/*
Buy when :
- Stochastic main over stochastic signal,
- RSI over 65, // was 50
- BearsPower over 0,
- Price over parabolic SAR,
- Fast moving average over slow moving average,
- Price action option.
*/
double openPrice = Open[ barID ];
if( ( StoM >StoS ) &&
( RSI > 65 ) && // was 50
( Bears > 0 ) &&
( openPrice > SAR ) &&
( imaFastCurrent > imaSlowPrevious ) &&
( ( false == PriceFilterEnabled ) || ( PriceFilterEnabled && ( Close[ 0 ] > Open[ 0 ] ) ) )
)
{
buySignalExists = true;
}
if( ( StoM < StoS ) &&
( RSI < 35 ) && // was 50
( Bears < 0 ) &&
( openPrice < SAR ) &&
( imaFastCurrent < imaSlowPrevious ) &&
( ( false == PriceFilterEnabled ) || ( PriceFilterEnabled && ( Close[ 0 ] < Open[ 0 ] ) ) )
)
{
sellSignalExists = true;
}
bool executeBuyTrade = false,
executeSellTrade = false;
if( buySignalExists )
{
if( ReverseSystem )
executeSellTrade = true;
else
executeBuyTrade = true;
}
else if( sellSignalExists )
{
if( ReverseSystem )
executeBuyTrade = true;
else
executeSellTrade = true;
}
// Check whether to open orders
if( ! ( executeBuyTrade || executeSellTrade ) )
{
g_BuySellState = ", waiting for signal...";
return;
}
// }
// Keep user's variable intact
g_tradingLots = Lots;
// Handle risk management
if( MMEnabled )
calculateLotsSize();
calculateOrderSizes();
if( executeBuyTrade )
{
Print("calling openBuyOrder()...");
openBuyOrder( barID );
}
else if( executeSellTrade )
{
Print("calling openSellOrder()...");
openSellOrder( barID );
}
}
// Opens buy order.
// barIndex: The index of the bar to be used for calculations.
// Returns the ticket of the first opened order.
int openBuyOrder( int barIndex )
{
double stopLoss = calculateBuyStopLoss( barIndex ),
takeProfit = calculateBuyTakeProfit( barIndex ),
orderOpenPrice,
// The order size of both orders
orderSize;
int ticket1,
ticket2,
expire = 0;
// if( Expiration > 0 )
// expire = TimeCurrent() + ( Expiration * 60 ) - 5;
if(NewBarBuy() == true)
{
string instrument = Symbol();
orderOpenPrice = High[ barIndex ] + MarginPips * Point;
ticket1 = OrderSend( instrument, OP_BUYSTOP, g_order1Size, orderOpenPrice, Slippage, stopLoss, takeProfit, EAName, Magic1, expire, g_colorLong );
logOrderSendInfo( "Buy 1 info: ", instrument, g_order1Size, orderOpenPrice, Slippage, stopLoss, takeProfit, GetLastError() );
ticket2 = OrderSend( instrument, OP_BUYSTOP, g_order2Size, orderOpenPrice, Slippage, stopLoss, takeProfit, EAName, Magic2, expire, g_colorLong );
logOrderSendInfo( "Buy 2 info: ", instrument, g_order2Size, orderOpenPrice, Slippage, stopLoss, takeProfit, GetLastError() );
g_BuySellState = ", buy order open...";
}
else
{
string temp = "...";
if(g_lastBuyOrderBarId == -1)
temp = ", g_lastBuyOrderBarId == -1";
Print(StringConcatenate("NewBarBuy() false", temp));
}
if( ( ticket1 > 0 ) && ( ticket2 > 0 ) )
return (ticket1);
return (-1);
}
// Opens sell order.
// barIndex: The index of the bar to be used for calculations.
// Returns the ticket of the first opened order.
int openSellOrder( int barIndex )
{
double stopLoss = calculateSellStopLoss( barIndex ),
takeProfit = calculateSellTakeProfit( barIndex ),
orderOpenPrice,
// The order size of both orders
orderSize,
// order1Size
order1Size,
// order2Size
order2Size;
int ticket1,
ticket2,
expire = 0;
// if( Expiration > 0 )
// expire = TimeCurrent() + ( Expiration * 60 ) - 5;
if(NewBarSell() == true)
{
string instrument = Symbol();
orderOpenPrice = Low[ barIndex ] - MarginPips * Point;
ticket1 = OrderSend( instrument, OP_SELLSTOP, g_order1Size, orderOpenPrice, Slippage, stopLoss, takeProfit, EAName, Magic1, expire, g_colorShort );
logOrderSendInfo( "Sell 1 info: ", instrument, g_order1Size, orderOpenPrice, Slippage, stopLoss, takeProfit, GetLastError() );
ticket2 = OrderSend( instrument, OP_SELLSTOP, g_order2Size, orderOpenPrice, Slippage, stopLoss, takeProfit, EAName, Magic2, expire, g_colorShort );
logOrderSendInfo( "Sell 2 info: ", instrument, g_order2Size, orderOpenPrice, Slippage, stopLoss, takeProfit, GetLastError() );
g_BuySellState = ", sell order open...";
}
else
{
string temp = "...";
if(g_lastSellOrderBarId == -1)
temp = ", g_lastSellOrderBarId == -1";
Print(StringConcatenate("NewBarSell() false", temp));
}
if( ( ticket1 > 0 ) && ( ticket2 > 0 ) )
return (ticket1);
// TODO: Output the order failure reason to the window...
// if( ERR_NOT_ENOUGH_MONEY == GetLastError() )
if( ERR_NOT_ENOUGH_MONEY == GetLastError() )
{
Print( "Not enough money!" );
}
return (-1);
}
// Calculates the stop loss for buy order.
// barIndex: The index of the bar to be used for calculations.
// Returns the stop loss for the buy order.
double calculateBuyStopLoss( int barIndex )
{
double buyStopLoss = 0.0;
if( StopLoss > 0 )
{
buyStopLoss = Low[ barIndex ] - ( MarginPips + StopLoss ) * Point - NormalizeDouble( ( iATR( Symbol(), 0, 14, 1 ) / 10 ) * 0.5, Digits );
//buyStopLoss = Low[ barIndex ] - ( MarginPips + StopLoss )* Point + NormalizeDouble( ( iATR( Symbol(), 0, 14, 1 ) / 10 ) * 0.5, Digits );
Print(StringConcatenate("Buy with stop loss: ", DoubleToStr(buyStopLoss, Digits)));
}
return (buyStopLoss);
}
// Calculates the take profit for sell order.
// barIndex: The index of the bar to be used for calculations.
// Returns the take profit for the sell order.
double calculateSellTakeProfit( int barIndex )
{
double sellTakeProfit = 0.0;
if( TakeProfit > 0 )
{
sellTakeProfit = Low[ barIndex ] - ( MarginPips + TakeProfit ) * Point;
}
return (sellTakeProfit);
}
// Calculates the stop loss for sell order.
// barIndex: The index of the bar to be used for calculations.
// Returns the stop loss for the sell order.
double calculateSellStopLoss( int barIndex )
{
double sellStopLoss = 0.0;
if( StopLoss > 0 )
{
sellStopLoss = High[ barIndex ] + ( MarginPips + StopLoss ) * Point + NormalizeDouble( ( iATR( Symbol(), 0, 14, 1 ) / 10 ) * 0.5, Digits );
}
return (sellStopLoss);
}
double calculateBuyTakeProfit( int barID )
{
double buyTakeProfit = 0.0;
if( TakeProfit > 0 )
{
buyTakeProfit = High[ barID ] + ( MarginPips + TakeProfit ) * Point;
}
return (buyTakeProfit);
}
// Performs time filtering logic.
// Returns true if trading is allowed, false otherwise.
void doTimeFiltering()
{
int dayOfWeek = DayOfWeek(),
serverHour = Hour();
// Treat sunday trading
if( ( false == TradeOnSunday ) &&
( 0 == dayOfWeek )
)
{
g_tradingState = TRADING_STATE_WAITING;
return;
}
// Treat friday trading
if( 5 == dayOfWeek )
{
if( ! TradeOnFriday )
{
g_tradingState = TRADING_STATE_WAITING;
return;
}
if( ( serverHour >= FridayStartHour ) &&
( serverHour <= FridayEndHour )
)
{
g_tradingState = TRADING_STATE_TRADING;
return;
}
g_tradingState = TRADING_STATE_WAITING;
return;
}
// Treat monday through thursday
if( ! MondayToThursdayTFEnabled )
{
g_tradingState = TRADING_STATE_TRADING;
return;
}
if( ( dayOfWeek >= 1 ) &&
( dayOfWeek <= 4 ) &&
( serverHour >= MondayToThursdayStartHour ) &&
( serverHour <= MondayToThursdayEndHour )
)
{
g_tradingState = TRADING_STATE_TRADING;
return;
}
g_tradingState = TRADING_STATE_WAITING;
}
int closeBuyOrders( int orderMagic )
{
string instrument = Symbol();
double bidPrice = Bid;
int openOrdersCount = OrdersTotal(),
closedOrdersCount = 0;
for( int curOrder = ( openOrdersCount - 1 ); curOrder >= 0; curOrder-- )
{
// Select current order for further processing
OrderSelect( curOrder, SELECT_BY_POS, MODE_TRADES );
if( ( OrderMagicNumber() == orderMagic ) &&
( OrderSymbol() == instrument )
)
{
if( OP_BUY == OrderType() )
{
// TODO: add error handling
OrderClose( OrderTicket(), OrderLots(), bidPrice, Slippage );
closedOrdersCount++;
}
}
}
return (closedOrdersCount);
}
int closeSellOrders( int orderMagic )
{
string instrument = Symbol();
double askPrice = Ask;
int openOrdersCount = OrdersTotal(),
closedOrdersCount = 0;
for( int curOrder = ( openOrdersCount - 1 ); curOrder >= 0; curOrder-- )
{
// Select current order for further processing
OrderSelect( curOrder, SELECT_BY_POS, MODE_TRADES );
if( ( OrderMagicNumber() == orderMagic ) &&
( OrderSymbol() == instrument )
)
{
if( OP_SELL == OrderType() )
{
// TODO: add error handling
OrderClose( OrderTicket(), OrderLots(), askPrice, Slippage );
closedOrdersCount++;
}
}
}
return (closedOrdersCount);
}
int calculateOpenedOrdersCount()
{
int buyOrdersCount = calculateOrdersCount( OP_BUY, Magic1 ) + calculateOrdersCount( OP_BUY, Magic2 );
int sellOrdersCount = calculateOrdersCount( OP_SELL, Magic1 ) + calculateOrdersCount( OP_SELL, Magic2 );
return (buyOrdersCount + sellOrdersCount);
}
// Calculate the number of orders of specified type with specified magic number.
int calculateOrdersCount( int orderType, int orderMagic )
{
string instrument = Symbol();
int ordersCount = 0;
for( int i = 0; i < OrdersTotal(); i++ )
{
// Selects an order for further processing
bool orderSelected = OrderSelect( i, SELECT_BY_POS, MODE_TRADES );
if( orderSelected && ( OrderSymbol() == instrument ) )
{
if( ( OrderType() == orderType ) &&
( OrderMagicNumber() == orderMagic ) || ( 0 == orderMagic )
)
ordersCount++;
}
}
return (ordersCount);
}
// Recalculates and updates trailing stops
// of the opened orders.
void updateTrailingStopLosses()
{
for( int curOrder = 0; curOrder < OrdersTotal(); curOrder++ )
{
updateOrderTrailingStopLoss( curOrder );
}
}
// Updates the trailing stop loss for the specified order.
// Returns true if the trailing stop loss had been updated,
// false otherwise.
bool updateOrderTrailingStopLoss( int orderIndex )
{
OrderSelect( orderIndex, SELECT_BY_POS, MODE_TRADES );
string orderInstrument = OrderSymbol();
int orderType = OrderType(),
orderMagic = OrderMagicNumber(),
orderTicket = OrderTicket(),
digitsCount = Digits;
double askPrice = Ask,
bidPrice = Bid,
openPrice = OrderOpenPrice(),
normalizedOpenPrice = NormalizeDouble( openPrice, digitsCount ),
stopLoss = OrderStopLoss(),
takeProfit = OrderTakeProfit(),
normalizedStopLoss = NormalizeDouble( stopLoss, digitsCount ),
ATRValue = iATR( orderInstrument, ATRTSTimeFrame, ATRTSPeriod, 1 ) * ATRTSFactor,
normalizedATRValue = NormalizeDouble( ATRValue, digitsCount ),
normalizedBidATRDelta = NormalizeDouble( bidPrice - ATRValue, digitsCount ),
normalizedOpenPrice_BidDelta = NormalizeDouble( bidPrice - openPrice, digitsCount );
bool res = false;
if( ( orderType <= OP_SELL ) &&
( orderInstrument == Symbol() ) &&
( orderMagic == Magic2 )
)
{
if( ( OP_BUY == orderType ) &&
( ( askPrice - openPrice ) > ATRValue )
)
{
if( ( ATRTSPeriod > 0 ) &&
( askPrice > normalizedOpenPrice )
)
{
// MathAbs( stopLoss < EPSILON ) is a correct way of
// comparing doubles for equity.
if( ( normalizedStopLoss < normalizedBidATRDelta ) ||
MathAbs( stopLoss < EPSILON )
)
{
res = OrderModify( orderTicket, openPrice, normalizedBidATRDelta, takeProfit, 0, g_colorLong );
logOrderModifyInfo(
"Trailing stop (buy)",
orderInstrument,
orderTicket,
openPrice,
normalizedBidATRDelta,
takeProfit,
GetLastError()
);
return(res);
}
}
}
else if( ( OP_SELL == orderType )&&
( normalizedOpenPrice_BidDelta > normalizedATRValue )
)
{
if( ( ATRTSPeriod > 0 ) &&
( bidPrice < normalizedOpenPrice )
)
{
double newStopLoss = NormalizeDouble( askPrice + ATRValue, digitsCount );
if( ( normalizedStopLoss > newStopLoss ) ||
( stopLoss < EPSILON )
)
{
res = OrderModify( orderTicket, openPrice, newStopLoss, takeProfit, 0, g_colorShort );
logOrderModifyInfo(
"Trailing stop (sell)",
orderInstrument,
orderTicket,
openPrice,
newStopLoss,
takeProfit,
GetLastError()
);
return (res);
}
}
}
}
return (false);
}
// Allow one action per bar
// Please clarify that
bool NewBarBuy()
{
if( g_PreviousBarTime1 != Time[ 0 ] || g_lastBuyOrderBarId == -1)
{
g_PreviousBarTime1 = Time[ 0 ];
g_lastBuyOrderBarId = 0;
return(true);
}
else
{
Print(StringConcatenate(TimeToStr(g_PreviousBarTime1,TIME_DATE|TIME_SECONDS), " == ", TimeToStr(Time[0], TIME_DATE|TIME_SECONDS)));
}
return(false);
}
// Allow one action per bar
// Please clarify that
bool NewBarSell()
{
bool result = false;
if( g_PreviousBarTime2 != Time[ 0 ] || g_lastSellOrderBarId == -1)
{
g_PreviousBarTime2 = Time[ 0 ];
g_lastSellOrderBarId = 0;
result = true;
}
else
{
Print(StringConcatenate(TimeToStr(g_PreviousBarTime2,TIME_DATE|TIME_SECONDS), " == ", TimeToStr(Time[0], TIME_DATE|TIME_SECONDS)));
}
return(result);
}
// Calculates the first and second order sizes.
void calculateOrderSizes()
{
g_tradingLots = Lots;
if( g_tradingLots < MinLots )
{
g_tradingLots = MinLots;
}
else if( g_tradingLots > MaxLots )
{
g_tradingLots = MaxLots;
}
g_order1Size = NormalizeDouble( g_tradingLots * ( LotsPercent1 / 100 ), 2 );
g_order2Size = NormalizeDouble( g_tradingLots * ( LotsPercent2 / 100 ), 2 );
}
// Calculates lot size based on risk and free margin.
void calculateLotsSize()
{
string symbol = Symbol();
double minLots = MarketInfo( symbol, MODE_MINLOT ),
maxLots = MarketInfo( symbol, MODE_MAXLOT );
Lots = AccountFreeMargin() / STANDARD_LOT_SIZE * RiskPercent;
Lots = MathMin( MaxLots, MathMax( MinLots, Lots ) );
if( minLots < 0.1 )
{
Lots = NormalizeDouble( Lots, 2 );
}
else if( minLots < 1 )
{
Lots = NormalizeDouble( Lots, 1 );
}
else
Lots = NormalizeDouble( Lots, 0 );
if( Lots < minLots )
Lots = minLots;
if( Lots > maxLots )
Lots = maxLots;
return (0);
}
// Displays status in the chart window
void displayStatus()
{
string expertStatus = EAName;
ObjectSetText(
g_labelEAName,
EAName,
FontSize,
g_fontName,
InformationColor
);
ObjectSet( g_labelSpreadCaption, OBJPROP_YDISTANCE, g_baseYOffset + FontSize * g_textDensingFactor );
ObjectSetText(
g_labelSpreadCaption,
"Spread status:",
FontSize,
g_fontName,
InformationColor
);
ObjectSet( g_labelSpreadStatus, OBJPROP_YDISTANCE, g_baseYOffset + FontSize * g_textDensingFactor * 2 );
ObjectSetText(
g_labelSpreadStatus,
prepareSpreadStatusString(),
FontSize,
g_fontName,
InformationColor
);
ObjectSet( g_labelTradingState, OBJPROP_YDISTANCE, g_baseYOffset + FontSize * g_textDensingFactor * 3 );
ObjectSetText(
g_labelTradingState,
prepareTradingStateString(),
FontSize,
g_fontName,
InformationColor
);
WindowRedraw();
}
void updateSpreadInfo()
{
string instrument = Symbol();
// Check whether current spread exceeds maximal allowed spread
g_currentSpread = MarketInfo( instrument, MODE_SPREAD );
if( g_currentSpread > g_maxSpread )
g_maxSpread = g_currentSpread;
if( g_currentSpread < g_minSpread )
g_minSpread = g_currentSpread;
}
string prepareSpreadStatusString()
{
string spreadStatus = StringConcatenate( " Maximal allowed: ", MaximalSpread );
spreadStatus = StringConcatenate( spreadStatus, ", Current: ", g_currentSpread );
spreadStatus = StringConcatenate( spreadStatus, ", Min: ", g_minSpread );
spreadStatus = StringConcatenate( spreadStatus, ", Max: ", g_maxSpread );
return (spreadStatus);
}
string prepareTradingStateString()
{
string tradingState = "Trading state: ";
switch( g_tradingState ) {
case TRADING_STATE_WAITING:
tradingState = StringConcatenate( tradingState, "waiting" );
break;
case TRADING_STATE_TRADING:
tradingState = StringConcatenate( tradingState, "trading" );
break;
default:
tradingState = StringConcatenate( tradingState, "undefined" );
} // switch( g_tradingState )
tradingState = StringConcatenate(tradingState, g_BuySellState);
return (tradingState);
}
void logOrderSendInfo(
string commonInfo,
string instrument,
double orderSize,
double openPrice,
int slippage,
double stopLoss,
double takeProfit,
int errorCode
)
{
// It is expected that this function should work
// only in tester
if( ! IsVisualMode() )
return;
string info = StringConcatenate(
commonInfo,
"instrument: ", instrument,
" order size: ", orderSize,
" open price: ", openPrice,
" slippage: ", slippage,
" stop loss: ", stopLoss,
" take profit: ", takeProfit
);
Print( info );
if( ERR_NO_ERROR == errorCode )
return;
Print( "Error info: ", errorCode, " description: ", getErrorDescription( errorCode ) );
}
void logOrderModifyInfo(
string commonInfo,
string instrument,
int orderTicket,
double openPrice,
double stopLoss,
double takeProfit,
int errorCode
)
{
// It is expected that this function should work
// only in tester
if( ! IsVisualMode() )
return;
string info = StringConcatenate(
commonInfo,
"instrument: ", instrument,
" ticket: ", orderTicket,
" open price: ", openPrice,
" stop loss: ", stopLoss,
" take profit: ", takeProfit
);
Print( info );
if( ERR_NO_ERROR == errorCode )
return;
Print( "Error info: ", errorCode, " description: ", getErrorDescription( errorCode ) );
}
string getErrorDescription( int errorCode )
{
string errorDescription = "";
switch( errorCode ) {
case ERR_NO_ERROR:
errorDescription = "No error returned.";
break;
case ERR_NO_RESULT:
errorDescription = "No error returned, but the result is unknown.";
break;
case ERR_COMMON_ERROR:
errorDescription = "Common error.";
break;
case ERR_INVALID_TRADE_PARAMETERS:
errorDescription = "Invalid trade parameters.";
break;
case ERR_SERVER_BUSY:
errorDescription = "Trade server is busy.";
break;
case ERR_OLD_VERSION:
errorDescription = "Old version of the client terminal.";
break;
case ERR_NO_CONNECTION:
errorDescription = "No connection with trade server.";
break;
case ERR_NOT_ENOUGH_RIGHTS:
errorDescription = "Not enough rights.";
break;
case ERR_TOO_FREQUENT_REQUESTS:
errorDescription = "Too frequent requests.";
break;
case ERR_MALFUNCTIONAL_TRADE:
errorDescription = "Malfunctional trade operation.";
break;
case ERR_ACCOUNT_DISABLED:
errorDescription = "Account disabled.";
break;
case ERR_INVALID_ACCOUNT:
errorDescription = "Invalid account.";
break;
case ERR_TRADE_TIMEOUT:
errorDescription = "Trade timeout.";
break;
case ERR_INVALID_PRICE:
errorDescription = "Invalid price.";
break;
case ERR_INVALID_STOPS:
errorDescription = "Invalid stops.";
break;
case ERR_INVALID_TRADE_VOLUME:
errorDescription = "Invalid trade volume.";
break;
case ERR_MARKET_CLOSED:
errorDescription = "Market is closed.";
break;
case ERR_TRADE_DISABLED:
errorDescription = "Trade is disabled.";
break;
case ERR_NOT_ENOUGH_MONEY:
errorDescription = "Not enough money.";
break;
case ERR_PRICE_CHANGED:
errorDescription = "Price changed.";
break;
case ERR_OFF_QUOTES:
errorDescription = "Off quotes.";
break;
case ERR_BROKER_BUSY:
errorDescription = "Broker is busy.";
break;
case ERR_REQUOTE:
errorDescription = "Requote.";
break;
case ERR_ORDER_LOCKED:
errorDescription = "Order is locked.";
break;
case ERR_LONG_POSITIONS_ONLY_ALLOWED:
errorDescription = "Long positions only allowed.";
break;
case ERR_TOO_MANY_REQUESTS:
errorDescription = "Too many requests.";
break;
case ERR_TRADE_MODIFY_DENIED:
errorDescription = "Modification denied because an order is too close to market.";
break;
case ERR_TRADE_CONTEXT_BUSY:
errorDescription = "Trade context is busy.";
break;
case ERR_TRADE_EXPIRATION_DENIED:
errorDescription = "Expirations are denied by broker.";
break;
case ERR_TRADE_TOO_MANY_ORDERS:
errorDescription = "The amount of opened and pending orders has reached the limit set by a broker.";
break;
case ERR_NO_MQLERROR:
errorDescription = "No error.";
break;
case ERR_WRONG_FUNCTION_POINTER:
errorDescription = "Wrong function pointer.";
break;
case ERR_ARRAY_INDEX_OUT_OF_RANGE:
errorDescription = "Array index is out of range.";
break;
case ERR_NO_MEMORY_FOR_CALL_STACK:
errorDescription = "No memory for function call stack.";
break;
case ERR_RECURSIVE_STACK_OVERFLOW:
errorDescription = "Recursive stack overflow.";
break;
case ERR_NOT_ENOUGH_STACK_FOR_PARAM:
errorDescription = "Not enough stack for parameter.";
break;
case ERR_NO_MEMORY_FOR_PARAM_STRING:
errorDescription = "No memory for parameter string.";
break;
case ERR_NO_MEMORY_FOR_TEMP_STRING:
errorDescription = "No memory for temporary string.";
break;
case ERR_NOT_INITIALIZED_STRING:
errorDescription = "Not initialized string.";
break;
case ERR_NOT_INITIALIZED_ARRAYSTRING:
errorDescription = "Not initialized string in an array.";
break;
case ERR_NO_MEMORY_FOR_ARRAYSTRING:
errorDescription = "No memory for an array string.";
break;
case ERR_TOO_LONG_STRING:
errorDescription = "Too long string.";
break;
case ERR_REMAINDER_FROM_ZERO_DIVIDE:
errorDescription = "Remainder from dividing by zero.";
break;
case ERR_ZERO_DIVIDE:
errorDescription = "Division by zero.";
break;
case ERR_UNKNOWN_COMMAND:
errorDescription = "Unknown command.";
break;
case ERR_WRONG_JUMP:
errorDescription = "Wrong jump.";
break;
case ERR_NOT_INITIALIZED_ARRAY:
errorDescription = "Not initialized array.";
break;
case ERR_DLL_CALLS_NOT_ALLOWED:
errorDescription = "DLL calls are not allowed.";
break;
case ERR_CANNOT_LOAD_LIBRARY:
errorDescription = "Cannot load library.";
break;
case ERR_CANNOT_CALL_FUNCTION:
errorDescription = "Cannot call function.";
break;
case ERR_EXTERNAL_CALLS_NOT_ALLOWED:
errorDescription = "EA function calls are not allowed.";
break;
case ERR_NO_MEMORY_FOR_RETURNED_STR:
errorDescription = "Not enough memory for a string returned from a function.";
break;
case ERR_SYSTEM_BUSY:
errorDescription = "System is busy.";
break;
case ERR_INVALID_FUNCTION_PARAMSCNT:
errorDescription = "Invalid function parameters count.";
break;
case ERR_INVALID_FUNCTION_PARAMVALUE:
errorDescription = "Invalid function parameter value.";
break;
case ERR_STRING_FUNCTION_INTERNAL:
errorDescription = "String function internal error.";
break;
case ERR_SOME_ARRAY_ERROR:
errorDescription = "Unspecified array error.";
break;
case ERR_INCORRECT_SERIESARRAY_USING:
errorDescription = "Using incorrect series array.";
break;
case ERR_CUSTOM_INDICATOR_ERROR:
errorDescription = "Custom indicator error.";
break;
case ERR_INCOMPATIBLE_ARRAYS:
errorDescription = "Arrays are incompatible.";
break;
case ERR_GLOBAL_VARIABLES_PROCESSING:
errorDescription = "Global variables processing error.";
break;
case ERR_GLOBAL_VARIABLE_NOT_FOUND:
errorDescription = "Global variable not found.";
break;
case ERR_FUNC_NOT_ALLOWED_IN_TESTING:
errorDescription = "Function is not allowed in testing mode.";
break;
case ERR_FUNCTION_NOT_CONFIRMED:
errorDescription = "Function is not confirmed.";
break;
case ERR_SEND_MAIL_ERROR:
errorDescription = "Mail sending error.";
break;
case ERR_STRING_PARAMETER_EXPECTED:
errorDescription = "String parameter expected.";
break;
case ERR_INTEGER_PARAMETER_EXPECTED:
errorDescription = "Integer parameter expected.";
break;
case ERR_DOUBLE_PARAMETER_EXPECTED:
errorDescription = "Double parameter expected.";
break;
case ERR_ARRAY_AS_PARAMETER_EXPECTED:
errorDescription = "Array as parameter expected.";
break;
case ERR_HISTORY_WILL_UPDATED:
errorDescription = "Requested history data in updating state.";
break;
case ERR_TRADE_ERROR:
errorDescription = "Some error in trade operation execution.";
break;
case ERR_END_OF_FILE:
errorDescription = "End of a file.";
break;
case ERR_SOME_FILE_ERROR:
errorDescription = "Unspecified file error.";
break;
case ERR_WRONG_FILE_NAME:
errorDescription = "Invalid file name.";
break;
case ERR_TOO_MANY_OPENED_FILES:
errorDescription = "Too many opened files.";
break;
case ERR_CANNOT_OPEN_FILE:
errorDescription = "Cannot open file.";
break;
case ERR_INCOMPATIBLE_FILEACCESS:
errorDescription = "Incompatible access to a file.";
break;
case ERR_NO_ORDER_SELECTED:
errorDescription = "No order selected.";
break;
case ERR_UNKNOWN_SYMBOL:
errorDescription = "Unknown symbol.";
break;
case ERR_INVALID_PRICE_PARAM:
errorDescription = "Invalid price.";
break;
case ERR_INVALID_TICKET:
errorDescription = "Invalid ticket.";
break;
case ERR_TRADE_NOT_ALLOWED:
errorDescription = "Trade is not allowed.";
break;
case ERR_LONGS_NOT_ALLOWED:
errorDescription = "Long tades are not allowed.";
break;
case ERR_SHORTS_NOT_ALLOWED:
errorDescription = "Short trades are not allowed.";
break;
case ERR_OBJECT_ALREADY_EXISTS:
errorDescription = "Object already exists.";
break;
case ERR_UNKNOWN_OBJECT_PROPERTY:
errorDescription = "Unknown object property.";
break;
case ERR_OBJECT_DOES_NOT_EXIST:
errorDescription = "Object does not exist.";
break;
case ERR_UNKNOWN_OBJECT_TYPE:
errorDescription = "Unknown object type.";
break;
case ERR_NO_OBJECT_NAME:
errorDescription = "No object name.";
break;
case ERR_OBJECT_COORDINATES_ERROR:
errorDescription = "Object coordinates error.";
break;
case ERR_NO_SPECIFIED_SUBWINDOW:
errorDescription = "No sub-window specified.";
break;
case ERR_SOME_OBJECT_ERROR:
errorDescription = "Unspecified error while operation on object.";
break;
} // switch( errorCode )
return (errorDescription);
}
J'ai réglé cette version.
On en reparle avec des résultats de tests ?
---------------------------------------------------------------------------------------------------
/*
+------------------------------------------------------------------+
| FunYooSalad v1.0.mq4 (was vForce Like EA v3.mq4) |
| portions Copyright © 2009, TradingSytemForex |
| http://www.tradingsystemforex.com |
| Additions by Furax pour forexagone.com le 04 Novembre 2011 | |
| Additions by Maxim Feinshtein [email protected] |
| Additions by William House [email protected] |
| you can modify this expert |
| you can change the name |
| you can add "modified by you", |
| but you are not allowed to erase the copyrights |
+------------------------------------------------------------------+
*/
#define EAName "FunYooSalad v1.0"
#property copyright "Copyright © 2009, TradingSytemForex"
#property link "http://www.tradingsystemforex.com"
#include <WinUser32.mqh>
#include <stderror.mqh>
#define STANDARD_LOT_SIZE 100000.0
// Used for souble values comparisons
#define EPSILON 0.00001
#define TRADING_STATE_WAITING 0
#define TRADING_STATE_TRADING 1
// funyoo, why don't we use GMT offset?
extern string S1 = "--- Stochastic filter settings";
extern int StochKPeriod = 5;
extern int StochDPeriod = 3;
extern int StochSlowing = 3;
extern string S2 = "--- RSI indicator settings";
extern int RSIPeriod = 8; // was 2 !...
extern string S3 = "--- Bears power indicator settings";
extern int BearsPeriod = 12;
extern string S4 = "--- Moving average indicator settings";
extern int FastMAPeriod = 19;
extern int SlowMAPeriod = 50;
extern string S5 = "--- Parabolic stop and reverse system settings";
extern double PSARStep = 0.003;
extern double PSARMaximum = 0.018;
extern string S6 = "--- Money management settings";
extern bool MMEnabled = false; // Flag, indicating whether risk management is enabled.
extern double Lots = 0.1; // Lots size
extern double LotsPercent1 = 80; // First order percent
extern double LotsPercent2 = 20; // Second order percent
extern double RiskPercent = 1; // The risk percentage
extern double MinLots = 0.01; // Minimal lots
extern double MaxLots = 1; // Maximal lots
extern bool PriceFilterEnabled = false;
extern string S7 = "--- Order Management";
// The maximal trading spread for the cuurency pair
extern double MaximalSpread = 5.0;
// funyoo, what does this parameter mean?
extern int MarginPips = 23;
// The default stop loss (PIPs)
extern int StopLoss = 69;
// The default take profit (PIPs)
extern int TakeProfit = 24; // was 24
// Maximal number of concurrent orders
extern int MaxOrders = 3; // was 8
// Maximal acceptable slippage
extern int Slippage = 3;
// The ID of the first order
extern int Magic1 = 20091;
// The ID of the second order
extern int Magic2 = 20092;
// Average true range trailing stop time frame
extern int ATRTSTimeFrame = 1;
// Average true range trailing stop period
extern int ATRTSPeriod = 14;
// Average true range trailing stop factor
extern double ATRTSFactor = 7;
extern string S8 = "--- Time filter settings";
// Flag, indicating whether to trade on sunday
extern bool TradeOnSunday = true;
// Flag, indicating whether to trade only at hours,
// specified for monday through thursday trading.
// It actually tells whether monday to thursday time
// filtering is enabled.
extern bool MondayToThursdayTFEnabled = false;
// The start hour for monday through thursday trading.
extern int MondayToThursdayStartHour = 0;
// The end hour for monday through thursday trading.
extern int MondayToThursdayEndHour = 24;
// Flag, indicating whether to trade on friday
extern bool TradeOnFriday = true;
// The start hour for friday trading.
extern int FridayStartHour = 0;
// The end hour for friday trading.
extern int FridayEndHour = 21;
// Flag, indicating whether to close open trades
// when in non-trade hours (outside the time filter)
extern bool CloseOrdersInNonTradeHours = false;
extern string S9 = "--- Graphics settings";
extern color InformationColor = LightGreen;
extern int FontSize = 12;
extern string S10 = "--- Miscellaneous settings";
// Expiration in minutes for the reverse pending order,
// causes the ERR_TRADE_EXPIRATION_DENIED error.
// funyoo, when is it needed?
// Buy instead of sell, sell instead of buy
extern bool ReverseSystem = true; // was false
// funyoo, this caues oder send error,
// can you please refine the implementation?
extern int Expiration = 1; // was 0
// Graphical entities names.
string g_labelEAName = "labelEAName",
g_labelSpreadCaption = "labelSpreadCaption",
g_labelSpreadStatus = "labelSpreadStatus",
g_labelTradingState = "labelTradingState";
string g_fontName = "Times New Roman";
string g_BuySellState = "";
datetime g_PreviousBarTime1;
datetime g_PreviousBarTime2;
// Long and short arrows colors
color g_colorLong = Blue,
g_colorShort = Orange; // was Red
// Either Lots, specified by user or calclated
// according to risk settings
double g_tradingLots;
double g_order1Size,
g_order2Size;
// Fix for 5-digit brokers
int g_digits;
double g_point;
// Minimal and maximal spreads during
// treading session.
double g_currentSpread,
g_minSpread,
g_maxSpread;
// Controls how far or near are text lines on Y axis.
double g_textDensingFactor = 1.5;
// Either TRADING_STATE_WAITING or TRADING_STATE_TRADING
int g_tradingState = TRADING_STATE_WAITING;
// The offset of the first expert status string in pixels.
int g_baseXOffset = 15,
g_baseYOffset = 20;
// Last order Bar Id - -1 means no last order
int g_lastBuyOrderBarId = -1;
int g_lastSellOrderBarId = -1;
// The expert initialization function
int init()
{
initGraphics();
g_currentSpread = MarketInfo( Symbol(), MODE_SPREAD );
g_minSpread = g_currentSpread;
g_maxSpread = g_currentSpread;
g_PreviousBarTime1 = D'2004.01.01 00:00';
g_PreviousBarTime2 = D'2004.01.01 00:00';
g_point = GetPoints();
g_lastBuyOrderBarId = -1;
g_lastSellOrderBarId = -1;
updateSpreadInfo();
displayStatus();
return (0);
}
double GetPoints()
{
if(Digits==3 || Digits==5)g_point=Point*10;
else g_point=Point;
return(g_point);
}
// The expert uninitialization function
int deinit()
{
deinitGraphics();
return (0);
}
int start()
{
// Update trailing stop
if( ATRTSPeriod > 0 )
updateTrailingStopLosses();
updateSpreadInfo();
// Do time filtering
doTimeFiltering();
displayStatus();
if( TRADING_STATE_TRADING == g_tradingState )
{
doTradingLogic();
}
else if( CloseOrdersInNonTradeHours )
{
closeBuyOrders( Magic1 );
closeBuyOrders( Magic2 );
closeSellOrders( Magic1 );
closeSellOrders( Magic2 );
}
return (0);
}
// Initializes graphical objects
void initGraphics()
{
// Added to the main chart window.
ObjectCreate( g_labelEAName, OBJ_LABEL, 0, 0, 0 );
ObjectCreate( g_labelSpreadCaption, OBJ_LABEL, 0, 0, 0 );
ObjectCreate( g_labelSpreadStatus, OBJ_LABEL, 0, 0, 0 );
ObjectCreate( g_labelTradingState, OBJ_LABEL, 0, 0, 0 );
// Bind to top left corner
ObjectSet( g_labelEAName, OBJPROP_CORNER, 0 );
ObjectSet( g_labelSpreadCaption, OBJPROP_CORNER, 0 );
ObjectSet( g_labelSpreadStatus, OBJPROP_CORNER, 0 );
ObjectSet( g_labelTradingState, OBJPROP_CORNER, 0 );
// Set EA name cordinates
ObjectSet( g_labelEAName, OBJPROP_XDISTANCE, g_baseXOffset );
ObjectSet( g_labelEAName, OBJPROP_YDISTANCE, g_baseYOffset );
// Set spread caption X cordinate;
// the Y coordinate is calculated since depends on font size.
ObjectSet( g_labelSpreadCaption, OBJPROP_XDISTANCE, g_baseXOffset );
// Set spread status X cordinate;
// the Y coordinate is calculated since depends on font size.
ObjectSet( g_labelSpreadStatus, OBJPROP_XDISTANCE, g_baseXOffset );
// Set trading status X cordinate;
// the Y coordinate is calculated since depends on font size.
ObjectSet( g_labelTradingState, OBJPROP_XDISTANCE, g_baseXOffset );
}
// Releases used graphical objects
void deinitGraphics()
{
// Release used graphics resources
ObjectDelete( g_labelEAName );
ObjectDelete( g_labelSpreadCaption );
ObjectDelete( g_labelSpreadStatus );
ObjectDelete( g_labelTradingState );
}
// Performs trading logic
void doTradingLogic()
{
// Check whether it is possible to open more orders
int openedOrdersCount = calculateOpenedOrdersCount();
if( openedOrdersCount >= MaxOrders )
{
Print( "Maximal number of orders is already opened..." );
return;
}
string instrument = Symbol();
// Check whether current spread exceeds maximal allowed spread
double currentSpread = MarketInfo( instrument, MODE_SPREAD );
if( currentSpread > MaximalSpread )
{
Print(
"Current spread ",
NormalizeDouble( currentSpread, 1 ),
"exceeds maximal allowed spread ",
MaximalSpread
);
return;
}
// funyoo: why to use constant value?
int barID = 1;
// for( int i = 1; i <= limit; i++ )
// {
// Check for trade signal
// Retrieve 'stochastic oscillator' values
double StoMa = iStochastic( instrument, 0, StochKPeriod, StochDPeriod, StochSlowing, MODE_SMA, 0, MODE_MAIN, barID + 1 );
double StoM = iStochastic( instrument, 0, StochKPeriod, StochDPeriod, StochSlowing, MODE_SMA, 0, MODE_MAIN, barID );
double StoSa = iStochastic( instrument, 0, StochKPeriod, StochDPeriod, StochSlowing, MODE_SMA, 0, MODE_SIGNAL, barID + 1 );
double StoS = iStochastic( instrument, 0, StochKPeriod, StochDPeriod, StochSlowing, MODE_SMA, 0, MODE_SIGNAL, barID );
// Retrieve 'relative strength index' values
double RSIa = iRSI( instrument, 0, RSIPeriod, PRICE_CLOSE, barID + 1 );
double RSI = iRSI( instrument, 0, RSIPeriod, PRICE_CLOSE, barID );
// Retrieve 'bears power indicator' values
double Bearsa = iBearsPower( instrument, 0, BearsPeriod, PRICE_CLOSE, barID + 1 );
double Bears = iBearsPower( instrument, 0, BearsPeriod, PRICE_CLOSE, barID );
// Retrieve 'parabolic stop and reverse system' values
double SARa = iSAR( instrument, 0, PSARStep, PSARMaximum, barID + 1 );
double SAR = iSAR( instrument, 0, PSARStep, PSARMaximum, barID );
// Retrieve 'moving average' indicator svalues.
double imaFastCurrent = iMA( instrument, 0, FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE, barID ),
imaSlowPrevious = iMA( instrument, 0, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE, barID + 1 );
bool buySignalExists = false,
sellSignalExists = false;
/*
Buy when :
- Stochastic main over stochastic signal,
- RSI over 65, // was 50
- BearsPower over 0,
- Price over parabolic SAR,
- Fast moving average over slow moving average,
- Price action option.
*/
double openPrice = Open[ barID ];
if( ( StoM >StoS ) &&
( RSI > 65 ) && // was 50
( Bears > 0 ) &&
( openPrice > SAR ) &&
( imaFastCurrent > imaSlowPrevious ) &&
( ( false == PriceFilterEnabled ) || ( PriceFilterEnabled && ( Close[ 0 ] > Open[ 0 ] ) ) )
)
{
buySignalExists = true;
}
if( ( StoM < StoS ) &&
( RSI < 35 ) && // was 50
( Bears < 0 ) &&
( openPrice < SAR ) &&
( imaFastCurrent < imaSlowPrevious ) &&
( ( false == PriceFilterEnabled ) || ( PriceFilterEnabled && ( Close[ 0 ] < Open[ 0 ] ) ) )
)
{
sellSignalExists = true;
}
bool executeBuyTrade = false,
executeSellTrade = false;
if( buySignalExists )
{
if( ReverseSystem )
executeSellTrade = true;
else
executeBuyTrade = true;
}
else if( sellSignalExists )
{
if( ReverseSystem )
executeBuyTrade = true;
else
executeSellTrade = true;
}
// Check whether to open orders
if( ! ( executeBuyTrade || executeSellTrade ) )
{
g_BuySellState = ", waiting for signal...";
return;
}
// }
// Keep user's variable intact
g_tradingLots = Lots;
// Handle risk management
if( MMEnabled )
calculateLotsSize();
calculateOrderSizes();
if( executeBuyTrade )
{
Print("calling openBuyOrder()...");
openBuyOrder( barID );
}
else if( executeSellTrade )
{
Print("calling openSellOrder()...");
openSellOrder( barID );
}
}
// Opens buy order.
// barIndex: The index of the bar to be used for calculations.
// Returns the ticket of the first opened order.
int openBuyOrder( int barIndex )
{
double stopLoss = calculateBuyStopLoss( barIndex ),
takeProfit = calculateBuyTakeProfit( barIndex ),
orderOpenPrice,
// The order size of both orders
orderSize;
int ticket1,
ticket2,
expire = 0;
// if( Expiration > 0 )
// expire = TimeCurrent() + ( Expiration * 60 ) - 5;
if(NewBarBuy() == true)
{
string instrument = Symbol();
orderOpenPrice = High[ barIndex ] + MarginPips * Point;
ticket1 = OrderSend( instrument, OP_BUYSTOP, g_order1Size, orderOpenPrice, Slippage, stopLoss, takeProfit, EAName, Magic1, expire, g_colorLong );
logOrderSendInfo( "Buy 1 info: ", instrument, g_order1Size, orderOpenPrice, Slippage, stopLoss, takeProfit, GetLastError() );
ticket2 = OrderSend( instrument, OP_BUYSTOP, g_order2Size, orderOpenPrice, Slippage, stopLoss, takeProfit, EAName, Magic2, expire, g_colorLong );
logOrderSendInfo( "Buy 2 info: ", instrument, g_order2Size, orderOpenPrice, Slippage, stopLoss, takeProfit, GetLastError() );
g_BuySellState = ", buy order open...";
}
else
{
string temp = "...";
if(g_lastBuyOrderBarId == -1)
temp = ", g_lastBuyOrderBarId == -1";
Print(StringConcatenate("NewBarBuy() false", temp));
}
if( ( ticket1 > 0 ) && ( ticket2 > 0 ) )
return (ticket1);
return (-1);
}
// Opens sell order.
// barIndex: The index of the bar to be used for calculations.
// Returns the ticket of the first opened order.
int openSellOrder( int barIndex )
{
double stopLoss = calculateSellStopLoss( barIndex ),
takeProfit = calculateSellTakeProfit( barIndex ),
orderOpenPrice,
// The order size of both orders
orderSize,
// order1Size
order1Size,
// order2Size
order2Size;
int ticket1,
ticket2,
expire = 0;
// if( Expiration > 0 )
// expire = TimeCurrent() + ( Expiration * 60 ) - 5;
if(NewBarSell() == true)
{
string instrument = Symbol();
orderOpenPrice = Low[ barIndex ] - MarginPips * Point;
ticket1 = OrderSend( instrument, OP_SELLSTOP, g_order1Size, orderOpenPrice, Slippage, stopLoss, takeProfit, EAName, Magic1, expire, g_colorShort );
logOrderSendInfo( "Sell 1 info: ", instrument, g_order1Size, orderOpenPrice, Slippage, stopLoss, takeProfit, GetLastError() );
ticket2 = OrderSend( instrument, OP_SELLSTOP, g_order2Size, orderOpenPrice, Slippage, stopLoss, takeProfit, EAName, Magic2, expire, g_colorShort );
logOrderSendInfo( "Sell 2 info: ", instrument, g_order2Size, orderOpenPrice, Slippage, stopLoss, takeProfit, GetLastError() );
g_BuySellState = ", sell order open...";
}
else
{
string temp = "...";
if(g_lastSellOrderBarId == -1)
temp = ", g_lastSellOrderBarId == -1";
Print(StringConcatenate("NewBarSell() false", temp));
}
if( ( ticket1 > 0 ) && ( ticket2 > 0 ) )
return (ticket1);
// TODO: Output the order failure reason to the window...
// if( ERR_NOT_ENOUGH_MONEY == GetLastError() )
if( ERR_NOT_ENOUGH_MONEY == GetLastError() )
{
Print( "Not enough money!" );
}
return (-1);
}
// Calculates the stop loss for buy order.
// barIndex: The index of the bar to be used for calculations.
// Returns the stop loss for the buy order.
double calculateBuyStopLoss( int barIndex )
{
double buyStopLoss = 0.0;
if( StopLoss > 0 )
{
buyStopLoss = Low[ barIndex ] - ( MarginPips + StopLoss ) * Point - NormalizeDouble( ( iATR( Symbol(), 0, 14, 1 ) / 10 ) * 0.5, Digits );
//buyStopLoss = Low[ barIndex ] - ( MarginPips + StopLoss )* Point + NormalizeDouble( ( iATR( Symbol(), 0, 14, 1 ) / 10 ) * 0.5, Digits );
Print(StringConcatenate("Buy with stop loss: ", DoubleToStr(buyStopLoss, Digits)));
}
return (buyStopLoss);
}
// Calculates the take profit for sell order.
// barIndex: The index of the bar to be used for calculations.
// Returns the take profit for the sell order.
double calculateSellTakeProfit( int barIndex )
{
double sellTakeProfit = 0.0;
if( TakeProfit > 0 )
{
sellTakeProfit = Low[ barIndex ] - ( MarginPips + TakeProfit ) * Point;
}
return (sellTakeProfit);
}
// Calculates the stop loss for sell order.
// barIndex: The index of the bar to be used for calculations.
// Returns the stop loss for the sell order.
double calculateSellStopLoss( int barIndex )
{
double sellStopLoss = 0.0;
if( StopLoss > 0 )
{
sellStopLoss = High[ barIndex ] + ( MarginPips + StopLoss ) * Point + NormalizeDouble( ( iATR( Symbol(), 0, 14, 1 ) / 10 ) * 0.5, Digits );
}
return (sellStopLoss);
}
double calculateBuyTakeProfit( int barID )
{
double buyTakeProfit = 0.0;
if( TakeProfit > 0 )
{
buyTakeProfit = High[ barID ] + ( MarginPips + TakeProfit ) * Point;
}
return (buyTakeProfit);
}
// Performs time filtering logic.
// Returns true if trading is allowed, false otherwise.
void doTimeFiltering()
{
int dayOfWeek = DayOfWeek(),
serverHour = Hour();
// Treat sunday trading
if( ( false == TradeOnSunday ) &&
( 0 == dayOfWeek )
)
{
g_tradingState = TRADING_STATE_WAITING;
return;
}
// Treat friday trading
if( 5 == dayOfWeek )
{
if( ! TradeOnFriday )
{
g_tradingState = TRADING_STATE_WAITING;
return;
}
if( ( serverHour >= FridayStartHour ) &&
( serverHour <= FridayEndHour )
)
{
g_tradingState = TRADING_STATE_TRADING;
return;
}
g_tradingState = TRADING_STATE_WAITING;
return;
}
// Treat monday through thursday
if( ! MondayToThursdayTFEnabled )
{
g_tradingState = TRADING_STATE_TRADING;
return;
}
if( ( dayOfWeek >= 1 ) &&
( dayOfWeek <= 4 ) &&
( serverHour >= MondayToThursdayStartHour ) &&
( serverHour <= MondayToThursdayEndHour )
)
{
g_tradingState = TRADING_STATE_TRADING;
return;
}
g_tradingState = TRADING_STATE_WAITING;
}
int closeBuyOrders( int orderMagic )
{
string instrument = Symbol();
double bidPrice = Bid;
int openOrdersCount = OrdersTotal(),
closedOrdersCount = 0;
for( int curOrder = ( openOrdersCount - 1 ); curOrder >= 0; curOrder-- )
{
// Select current order for further processing
OrderSelect( curOrder, SELECT_BY_POS, MODE_TRADES );
if( ( OrderMagicNumber() == orderMagic ) &&
( OrderSymbol() == instrument )
)
{
if( OP_BUY == OrderType() )
{
// TODO: add error handling
OrderClose( OrderTicket(), OrderLots(), bidPrice, Slippage );
closedOrdersCount++;
}
}
}
return (closedOrdersCount);
}
int closeSellOrders( int orderMagic )
{
string instrument = Symbol();
double askPrice = Ask;
int openOrdersCount = OrdersTotal(),
closedOrdersCount = 0;
for( int curOrder = ( openOrdersCount - 1 ); curOrder >= 0; curOrder-- )
{
// Select current order for further processing
OrderSelect( curOrder, SELECT_BY_POS, MODE_TRADES );
if( ( OrderMagicNumber() == orderMagic ) &&
( OrderSymbol() == instrument )
)
{
if( OP_SELL == OrderType() )
{
// TODO: add error handling
OrderClose( OrderTicket(), OrderLots(), askPrice, Slippage );
closedOrdersCount++;
}
}
}
return (closedOrdersCount);
}
int calculateOpenedOrdersCount()
{
int buyOrdersCount = calculateOrdersCount( OP_BUY, Magic1 ) + calculateOrdersCount( OP_BUY, Magic2 );
int sellOrdersCount = calculateOrdersCount( OP_SELL, Magic1 ) + calculateOrdersCount( OP_SELL, Magic2 );
return (buyOrdersCount + sellOrdersCount);
}
// Calculate the number of orders of specified type with specified magic number.
int calculateOrdersCount( int orderType, int orderMagic )
{
string instrument = Symbol();
int ordersCount = 0;
for( int i = 0; i < OrdersTotal(); i++ )
{
// Selects an order for further processing
bool orderSelected = OrderSelect( i, SELECT_BY_POS, MODE_TRADES );
if( orderSelected && ( OrderSymbol() == instrument ) )
{
if( ( OrderType() == orderType ) &&
( OrderMagicNumber() == orderMagic ) || ( 0 == orderMagic )
)
ordersCount++;
}
}
return (ordersCount);
}
// Recalculates and updates trailing stops
// of the opened orders.
void updateTrailingStopLosses()
{
for( int curOrder = 0; curOrder < OrdersTotal(); curOrder++ )
{
updateOrderTrailingStopLoss( curOrder );
}
}
// Updates the trailing stop loss for the specified order.
// Returns true if the trailing stop loss had been updated,
// false otherwise.
bool updateOrderTrailingStopLoss( int orderIndex )
{
OrderSelect( orderIndex, SELECT_BY_POS, MODE_TRADES );
string orderInstrument = OrderSymbol();
int orderType = OrderType(),
orderMagic = OrderMagicNumber(),
orderTicket = OrderTicket(),
digitsCount = Digits;
double askPrice = Ask,
bidPrice = Bid,
openPrice = OrderOpenPrice(),
normalizedOpenPrice = NormalizeDouble( openPrice, digitsCount ),
stopLoss = OrderStopLoss(),
takeProfit = OrderTakeProfit(),
normalizedStopLoss = NormalizeDouble( stopLoss, digitsCount ),
ATRValue = iATR( orderInstrument, ATRTSTimeFrame, ATRTSPeriod, 1 ) * ATRTSFactor,
normalizedATRValue = NormalizeDouble( ATRValue, digitsCount ),
normalizedBidATRDelta = NormalizeDouble( bidPrice - ATRValue, digitsCount ),
normalizedOpenPrice_BidDelta = NormalizeDouble( bidPrice - openPrice, digitsCount );
bool res = false;
if( ( orderType <= OP_SELL ) &&
( orderInstrument == Symbol() ) &&
( orderMagic == Magic2 )
)
{
if( ( OP_BUY == orderType ) &&
( ( askPrice - openPrice ) > ATRValue )
)
{
if( ( ATRTSPeriod > 0 ) &&
( askPrice > normalizedOpenPrice )
)
{
// MathAbs( stopLoss < EPSILON ) is a correct way of
// comparing doubles for equity.
if( ( normalizedStopLoss < normalizedBidATRDelta ) ||
MathAbs( stopLoss < EPSILON )
)
{
res = OrderModify( orderTicket, openPrice, normalizedBidATRDelta, takeProfit, 0, g_colorLong );
logOrderModifyInfo(
"Trailing stop (buy)",
orderInstrument,
orderTicket,
openPrice,
normalizedBidATRDelta,
takeProfit,
GetLastError()
);
return(res);
}
}
}
else if( ( OP_SELL == orderType )&&
( normalizedOpenPrice_BidDelta > normalizedATRValue )
)
{
if( ( ATRTSPeriod > 0 ) &&
( bidPrice < normalizedOpenPrice )
)
{
double newStopLoss = NormalizeDouble( askPrice + ATRValue, digitsCount );
if( ( normalizedStopLoss > newStopLoss ) ||
( stopLoss < EPSILON )
)
{
res = OrderModify( orderTicket, openPrice, newStopLoss, takeProfit, 0, g_colorShort );
logOrderModifyInfo(
"Trailing stop (sell)",
orderInstrument,
orderTicket,
openPrice,
newStopLoss,
takeProfit,
GetLastError()
);
return (res);
}
}
}
}
return (false);
}
// Allow one action per bar
// Please clarify that
bool NewBarBuy()
{
if( g_PreviousBarTime1 != Time[ 0 ] || g_lastBuyOrderBarId == -1)
{
g_PreviousBarTime1 = Time[ 0 ];
g_lastBuyOrderBarId = 0;
return(true);
}
else
{
Print(StringConcatenate(TimeToStr(g_PreviousBarTime1,TIME_DATE|TIME_SECONDS), " == ", TimeToStr(Time[0], TIME_DATE|TIME_SECONDS)));
}
return(false);
}
// Allow one action per bar
// Please clarify that
bool NewBarSell()
{
bool result = false;
if( g_PreviousBarTime2 != Time[ 0 ] || g_lastSellOrderBarId == -1)
{
g_PreviousBarTime2 = Time[ 0 ];
g_lastSellOrderBarId = 0;
result = true;
}
else
{
Print(StringConcatenate(TimeToStr(g_PreviousBarTime2,TIME_DATE|TIME_SECONDS), " == ", TimeToStr(Time[0], TIME_DATE|TIME_SECONDS)));
}
return(result);
}
// Calculates the first and second order sizes.
void calculateOrderSizes()
{
g_tradingLots = Lots;
if( g_tradingLots < MinLots )
{
g_tradingLots = MinLots;
}
else if( g_tradingLots > MaxLots )
{
g_tradingLots = MaxLots;
}
g_order1Size = NormalizeDouble( g_tradingLots * ( LotsPercent1 / 100 ), 2 );
g_order2Size = NormalizeDouble( g_tradingLots * ( LotsPercent2 / 100 ), 2 );
}
// Calculates lot size based on risk and free margin.
void calculateLotsSize()
{
string symbol = Symbol();
double minLots = MarketInfo( symbol, MODE_MINLOT ),
maxLots = MarketInfo( symbol, MODE_MAXLOT );
Lots = AccountFreeMargin() / STANDARD_LOT_SIZE * RiskPercent;
Lots = MathMin( MaxLots, MathMax( MinLots, Lots ) );
if( minLots < 0.1 )
{
Lots = NormalizeDouble( Lots, 2 );
}
else if( minLots < 1 )
{
Lots = NormalizeDouble( Lots, 1 );
}
else
Lots = NormalizeDouble( Lots, 0 );
if( Lots < minLots )
Lots = minLots;
if( Lots > maxLots )
Lots = maxLots;
return (0);
}
// Displays status in the chart window
void displayStatus()
{
string expertStatus = EAName;
ObjectSetText(
g_labelEAName,
EAName,
FontSize,
g_fontName,
InformationColor
);
ObjectSet( g_labelSpreadCaption, OBJPROP_YDISTANCE, g_baseYOffset + FontSize * g_textDensingFactor );
ObjectSetText(
g_labelSpreadCaption,
"Spread status:",
FontSize,
g_fontName,
InformationColor
);
ObjectSet( g_labelSpreadStatus, OBJPROP_YDISTANCE, g_baseYOffset + FontSize * g_textDensingFactor * 2 );
ObjectSetText(
g_labelSpreadStatus,
prepareSpreadStatusString(),
FontSize,
g_fontName,
InformationColor
);
ObjectSet( g_labelTradingState, OBJPROP_YDISTANCE, g_baseYOffset + FontSize * g_textDensingFactor * 3 );
ObjectSetText(
g_labelTradingState,
prepareTradingStateString(),
FontSize,
g_fontName,
InformationColor
);
WindowRedraw();
}
void updateSpreadInfo()
{
string instrument = Symbol();
// Check whether current spread exceeds maximal allowed spread
g_currentSpread = MarketInfo( instrument, MODE_SPREAD );
if( g_currentSpread > g_maxSpread )
g_maxSpread = g_currentSpread;
if( g_currentSpread < g_minSpread )
g_minSpread = g_currentSpread;
}
string prepareSpreadStatusString()
{
string spreadStatus = StringConcatenate( " Maximal allowed: ", MaximalSpread );
spreadStatus = StringConcatenate( spreadStatus, ", Current: ", g_currentSpread );
spreadStatus = StringConcatenate( spreadStatus, ", Min: ", g_minSpread );
spreadStatus = StringConcatenate( spreadStatus, ", Max: ", g_maxSpread );
return (spreadStatus);
}
string prepareTradingStateString()
{
string tradingState = "Trading state: ";
switch( g_tradingState ) {
case TRADING_STATE_WAITING:
tradingState = StringConcatenate( tradingState, "waiting" );
break;
case TRADING_STATE_TRADING:
tradingState = StringConcatenate( tradingState, "trading" );
break;
default:
tradingState = StringConcatenate( tradingState, "undefined" );
} // switch( g_tradingState )
tradingState = StringConcatenate(tradingState, g_BuySellState);
return (tradingState);
}
void logOrderSendInfo(
string commonInfo,
string instrument,
double orderSize,
double openPrice,
int slippage,
double stopLoss,
double takeProfit,
int errorCode
)
{
// It is expected that this function should work
// only in tester
if( ! IsVisualMode() )
return;
string info = StringConcatenate(
commonInfo,
"instrument: ", instrument,
" order size: ", orderSize,
" open price: ", openPrice,
" slippage: ", slippage,
" stop loss: ", stopLoss,
" take profit: ", takeProfit
);
Print( info );
if( ERR_NO_ERROR == errorCode )
return;
Print( "Error info: ", errorCode, " description: ", getErrorDescription( errorCode ) );
}
void logOrderModifyInfo(
string commonInfo,
string instrument,
int orderTicket,
double openPrice,
double stopLoss,
double takeProfit,
int errorCode
)
{
// It is expected that this function should work
// only in tester
if( ! IsVisualMode() )
return;
string info = StringConcatenate(
commonInfo,
"instrument: ", instrument,
" ticket: ", orderTicket,
" open price: ", openPrice,
" stop loss: ", stopLoss,
" take profit: ", takeProfit
);
Print( info );
if( ERR_NO_ERROR == errorCode )
return;
Print( "Error info: ", errorCode, " description: ", getErrorDescription( errorCode ) );
}
string getErrorDescription( int errorCode )
{
string errorDescription = "";
switch( errorCode ) {
case ERR_NO_ERROR:
errorDescription = "No error returned.";
break;
case ERR_NO_RESULT:
errorDescription = "No error returned, but the result is unknown.";
break;
case ERR_COMMON_ERROR:
errorDescription = "Common error.";
break;
case ERR_INVALID_TRADE_PARAMETERS:
errorDescription = "Invalid trade parameters.";
break;
case ERR_SERVER_BUSY:
errorDescription = "Trade server is busy.";
break;
case ERR_OLD_VERSION:
errorDescription = "Old version of the client terminal.";
break;
case ERR_NO_CONNECTION:
errorDescription = "No connection with trade server.";
break;
case ERR_NOT_ENOUGH_RIGHTS:
errorDescription = "Not enough rights.";
break;
case ERR_TOO_FREQUENT_REQUESTS:
errorDescription = "Too frequent requests.";
break;
case ERR_MALFUNCTIONAL_TRADE:
errorDescription = "Malfunctional trade operation.";
break;
case ERR_ACCOUNT_DISABLED:
errorDescription = "Account disabled.";
break;
case ERR_INVALID_ACCOUNT:
errorDescription = "Invalid account.";
break;
case ERR_TRADE_TIMEOUT:
errorDescription = "Trade timeout.";
break;
case ERR_INVALID_PRICE:
errorDescription = "Invalid price.";
break;
case ERR_INVALID_STOPS:
errorDescription = "Invalid stops.";
break;
case ERR_INVALID_TRADE_VOLUME:
errorDescription = "Invalid trade volume.";
break;
case ERR_MARKET_CLOSED:
errorDescription = "Market is closed.";
break;
case ERR_TRADE_DISABLED:
errorDescription = "Trade is disabled.";
break;
case ERR_NOT_ENOUGH_MONEY:
errorDescription = "Not enough money.";
break;
case ERR_PRICE_CHANGED:
errorDescription = "Price changed.";
break;
case ERR_OFF_QUOTES:
errorDescription = "Off quotes.";
break;
case ERR_BROKER_BUSY:
errorDescription = "Broker is busy.";
break;
case ERR_REQUOTE:
errorDescription = "Requote.";
break;
case ERR_ORDER_LOCKED:
errorDescription = "Order is locked.";
break;
case ERR_LONG_POSITIONS_ONLY_ALLOWED:
errorDescription = "Long positions only allowed.";
break;
case ERR_TOO_MANY_REQUESTS:
errorDescription = "Too many requests.";
break;
case ERR_TRADE_MODIFY_DENIED:
errorDescription = "Modification denied because an order is too close to market.";
break;
case ERR_TRADE_CONTEXT_BUSY:
errorDescription = "Trade context is busy.";
break;
case ERR_TRADE_EXPIRATION_DENIED:
errorDescription = "Expirations are denied by broker.";
break;
case ERR_TRADE_TOO_MANY_ORDERS:
errorDescription = "The amount of opened and pending orders has reached the limit set by a broker.";
break;
case ERR_NO_MQLERROR:
errorDescription = "No error.";
break;
case ERR_WRONG_FUNCTION_POINTER:
errorDescription = "Wrong function pointer.";
break;
case ERR_ARRAY_INDEX_OUT_OF_RANGE:
errorDescription = "Array index is out of range.";
break;
case ERR_NO_MEMORY_FOR_CALL_STACK:
errorDescription = "No memory for function call stack.";
break;
case ERR_RECURSIVE_STACK_OVERFLOW:
errorDescription = "Recursive stack overflow.";
break;
case ERR_NOT_ENOUGH_STACK_FOR_PARAM:
errorDescription = "Not enough stack for parameter.";
break;
case ERR_NO_MEMORY_FOR_PARAM_STRING:
errorDescription = "No memory for parameter string.";
break;
case ERR_NO_MEMORY_FOR_TEMP_STRING:
errorDescription = "No memory for temporary string.";
break;
case ERR_NOT_INITIALIZED_STRING:
errorDescription = "Not initialized string.";
break;
case ERR_NOT_INITIALIZED_ARRAYSTRING:
errorDescription = "Not initialized string in an array.";
break;
case ERR_NO_MEMORY_FOR_ARRAYSTRING:
errorDescription = "No memory for an array string.";
break;
case ERR_TOO_LONG_STRING:
errorDescription = "Too long string.";
break;
case ERR_REMAINDER_FROM_ZERO_DIVIDE:
errorDescription = "Remainder from dividing by zero.";
break;
case ERR_ZERO_DIVIDE:
errorDescription = "Division by zero.";
break;
case ERR_UNKNOWN_COMMAND:
errorDescription = "Unknown command.";
break;
case ERR_WRONG_JUMP:
errorDescription = "Wrong jump.";
break;
case ERR_NOT_INITIALIZED_ARRAY:
errorDescription = "Not initialized array.";
break;
case ERR_DLL_CALLS_NOT_ALLOWED:
errorDescription = "DLL calls are not allowed.";
break;
case ERR_CANNOT_LOAD_LIBRARY:
errorDescription = "Cannot load library.";
break;
case ERR_CANNOT_CALL_FUNCTION:
errorDescription = "Cannot call function.";
break;
case ERR_EXTERNAL_CALLS_NOT_ALLOWED:
errorDescription = "EA function calls are not allowed.";
break;
case ERR_NO_MEMORY_FOR_RETURNED_STR:
errorDescription = "Not enough memory for a string returned from a function.";
break;
case ERR_SYSTEM_BUSY:
errorDescription = "System is busy.";
break;
case ERR_INVALID_FUNCTION_PARAMSCNT:
errorDescription = "Invalid function parameters count.";
break;
case ERR_INVALID_FUNCTION_PARAMVALUE:
errorDescription = "Invalid function parameter value.";
break;
case ERR_STRING_FUNCTION_INTERNAL:
errorDescription = "String function internal error.";
break;
case ERR_SOME_ARRAY_ERROR:
errorDescription = "Unspecified array error.";
break;
case ERR_INCORRECT_SERIESARRAY_USING:
errorDescription = "Using incorrect series array.";
break;
case ERR_CUSTOM_INDICATOR_ERROR:
errorDescription = "Custom indicator error.";
break;
case ERR_INCOMPATIBLE_ARRAYS:
errorDescription = "Arrays are incompatible.";
break;
case ERR_GLOBAL_VARIABLES_PROCESSING:
errorDescription = "Global variables processing error.";
break;
case ERR_GLOBAL_VARIABLE_NOT_FOUND:
errorDescription = "Global variable not found.";
break;
case ERR_FUNC_NOT_ALLOWED_IN_TESTING:
errorDescription = "Function is not allowed in testing mode.";
break;
case ERR_FUNCTION_NOT_CONFIRMED:
errorDescription = "Function is not confirmed.";
break;
case ERR_SEND_MAIL_ERROR:
errorDescription = "Mail sending error.";
break;
case ERR_STRING_PARAMETER_EXPECTED:
errorDescription = "String parameter expected.";
break;
case ERR_INTEGER_PARAMETER_EXPECTED:
errorDescription = "Integer parameter expected.";
break;
case ERR_DOUBLE_PARAMETER_EXPECTED:
errorDescription = "Double parameter expected.";
break;
case ERR_ARRAY_AS_PARAMETER_EXPECTED:
errorDescription = "Array as parameter expected.";
break;
case ERR_HISTORY_WILL_UPDATED:
errorDescription = "Requested history data in updating state.";
break;
case ERR_TRADE_ERROR:
errorDescription = "Some error in trade operation execution.";
break;
case ERR_END_OF_FILE:
errorDescription = "End of a file.";
break;
case ERR_SOME_FILE_ERROR:
errorDescription = "Unspecified file error.";
break;
case ERR_WRONG_FILE_NAME:
errorDescription = "Invalid file name.";
break;
case ERR_TOO_MANY_OPENED_FILES:
errorDescription = "Too many opened files.";
break;
case ERR_CANNOT_OPEN_FILE:
errorDescription = "Cannot open file.";
break;
case ERR_INCOMPATIBLE_FILEACCESS:
errorDescription = "Incompatible access to a file.";
break;
case ERR_NO_ORDER_SELECTED:
errorDescription = "No order selected.";
break;
case ERR_UNKNOWN_SYMBOL:
errorDescription = "Unknown symbol.";
break;
case ERR_INVALID_PRICE_PARAM:
errorDescription = "Invalid price.";
break;
case ERR_INVALID_TICKET:
errorDescription = "Invalid ticket.";
break;
case ERR_TRADE_NOT_ALLOWED:
errorDescription = "Trade is not allowed.";
break;
case ERR_LONGS_NOT_ALLOWED:
errorDescription = "Long tades are not allowed.";
break;
case ERR_SHORTS_NOT_ALLOWED:
errorDescription = "Short trades are not allowed.";
break;
case ERR_OBJECT_ALREADY_EXISTS:
errorDescription = "Object already exists.";
break;
case ERR_UNKNOWN_OBJECT_PROPERTY:
errorDescription = "Unknown object property.";
break;
case ERR_OBJECT_DOES_NOT_EXIST:
errorDescription = "Object does not exist.";
break;
case ERR_UNKNOWN_OBJECT_TYPE:
errorDescription = "Unknown object type.";
break;
case ERR_NO_OBJECT_NAME:
errorDescription = "No object name.";
break;
case ERR_OBJECT_COORDINATES_ERROR:
errorDescription = "Object coordinates error.";
break;
case ERR_NO_SPECIFIED_SUBWINDOW:
errorDescription = "No sub-window specified.";
break;
case ERR_SOME_OBJECT_ERROR:
errorDescription = "Unspecified error while operation on object.";
break;
} // switch( errorCode )
return (errorDescription);
}