//=============================================================================
//           Console_2002_EA
//=============================================================================

#include <stdlib.mqh>
//+---------------------------------------------------+
//|Money Management                                   |
//+---------------------------------------------------+
extern double Lots = 0.01;
extern double MaximumRisk = 0.02;
extern double DecreaseFactor = 3;

//---- input parameters
extern int BrokerSpread = 2;
extern int TakeProfit = 60; // 0 deactivates Take Profit
extern int VolumeTime = 8;
extern int VolumeValue = 260;
extern int ATRperiod = 100;
extern double ATRlevel = 0.5;
extern int LCDEMAPeriod = 34; //Period EMA
extern int LCDLSMAPeriod = 25; // Period LSMA
extern int LCDFromZero = 3; // Distance from the zero level
extern bool OnlyLCDChange = true;
extern int Slippage = 3;

#define MAGIC 20070516

int init()
{
Comment("Waiting for the first tick...");
return(0);
}

int deinit()
{
Comment(WindowExpertName()," finished.");
return(0);
}

int start()
{
if(Bars<100)
{
Comment("Waiting for bars...");
return(0);
}

return(_LCDEA( Symbol(), Period(), MAGIC, LotsOptimized(), TakeProfit, Slippage,
BrokerSpread, VolumeTime, VolumeValue, LCDEMAPeriod, 
LCDLSMAPeriod, LCDFromZero,
OnlyLCDChange, ATRlevel, ATRperiod));
//return(_LCDEA( Symbol(), Period(), MAGIC, Lots, TakeProfit, Slippage,
//BrokerSpread, VolumeTime, VolumeValue, LCDEMAPeriod, 
//LCDLSMAPeriod, LCDFromZero,
//OnlyLCDChange, ATRlevel, ATRperiod));
}

int _LCDEA(string symbol, int period, int magic, double lots, int 
takeprofit, 
int slippage=3, int brokerSpread= 2, int volumeTime=2, int 
volumeValue= 10, 
int lCDEMAPeriod= 34, int lCDLSMAPeriod= 25, int 
lCDFromZero= 3,
bool onlyLCDChange= true, double atrlevel=0.3, int 
atrperiod=100)
{
// Internals
int _Digits = MarketInfo(symbol, MODE_DIGITS) ;
if(_Digits == 0) _Digits = 4;
double _Point = MarketInfo(symbol, MODE_POINT);
if(NormalizeDouble( _Point, _Digits) == 0.0) _Point = Point;
double _Bid = MarketInfo(symbol, MODE_BID);
double _Ask = MarketInfo(symbol, MODE_ASK);
string cm = "";

// Signals
static datetime bt = 0;
static bool _long = false;
static bool _short = false;
if(bt == 0) bt = iTime(symbol, period, 0);
if(bt != iTime(symbol, period, 0)){
double stoploss = 0.0;
bool trade = true;
for(int i = 1; i <= volumeTime; i++)
if(iVolume(symbol, period, i) < volumeValue) {
trade = false;
break;
}
if(trade)
{
int lcdy = iCustom(symbol, period, "LCD", lCDEMAPeriod, lCDLSMAPeriod, lCDFromZero, 0, 1);
int lcdb = iCustom(symbol, period, "LCD", lCDEMAPeriod, lCDLSMAPeriod, lCDFromZero, 1, 1);
int lcdy1 = iCustom(symbol, period, "LCD", lCDEMAPeriod, lCDLSMAPeriod, lCDFromZero, 0, 2);
int lcdb1 = iCustom(symbol, period, "LCD", lCDEMAPeriod, lCDLSMAPeriod, lCDFromZero, 1, 2);
_long = lcdb != EMPTY_VALUE && (lcdb1 == EMPTY_VALUE ||!onlyLCDChange) ;
_short = lcdy != EMPTY_VALUE && (lcdy1 == EMPTY_VALUE ||!onlyLCDChange) ;
if(_long)
for(i=0; i<Bars; i++){
double frac = iFractals(symbol, period, MODE_LOWER, i);
if(frac > _Point)
{
stoploss = NormalizeDouble( frac-iATR( symbol, period, atrperiod, 1)*atrlevel, _Digits);
break;
}
}
else if(_short)
for(i=0; i<Bars; i++){
frac = iFractals(symbol, period, MODE_UPPER, i);
if(frac > _Point)
{
stoploss = NormalizeDouble( frac+brokerSpread*_Point+ iATR(symbol, period, atrperiod, 1)*atrlevel, _Digits);
break;
}
}
}
}
// Signals

// S&R
bool _send_ok = false;
if(_long){
if(_LCDEA_IsPosition(OP_SELL, symbol, magic))
_OrderClose( OrderTicket( ), OrderLots(), OrderClosePrice( ), slippage, Red);
if(!_LCDEA_IsPosition(OP_BUY, symbol, magic))
_send_ok = _OrderSend(symbol, OP_BUY, _nv(symbol, lots), _Ask, slippage, stoploss, _tp(OP_BUY, symbol, takeprofit),WindowExpertName( ), magic, 0, Blue) > 0;
}
if(_short){
if(_LCDEA_IsPosition(OP_BUY, symbol, magic))
_OrderClose( OrderTicket( ), OrderLots(), OrderClosePrice( ), slippage, Blue);
if(!_LCDEA_IsPosition(OP_SELL, symbol, magic))
_send_ok = _OrderSend(symbol, OP_SELL, _nv(symbol, lots), _Bid, slippage, stoploss, _tp(OP_SELL, symbol, takeprofit),WindowExpertName( ), magic, 0, Red) > 0;
}
// S&R

// TrailingStop
for(i=0; i < OrdersTotal( ); i++)
if(OrderSelect( i, SELECT_BY_POS, MODE_TRADES) ){
if(OrderSymbol( ) == symbol)
if(OrderMagicNumber () == magic)
if(OrderType( ) == OP_BUY){
for(int j=0; j<Bars; j++){
frac = iFractals(symbol, period, MODE_LOWER, j);
if(frac > _Point)
{
stoploss = NormalizeDouble( frac-iATR( symbol, period, atrperiod, 1)*atrlevel, _Digits);
break;
}
}
if(MathRound( (stoploss- OrderStopLoss( ))/_Point) != 0)
if(!OrderModify( OrderTicket( ), OrderOpenPrice( ), stoploss, OrderTakeProfit( ),OrderExpiration( ), Blue))
Print("OrderModify( OP_BUY) error - ", ErrorDescription( GetLastError( ))); 
}else if(OrderType( ) == OP_SELL){
for(j=0; j<Bars; j++){
frac = iFractals(symbol, period, MODE_UPPER, j);
if(frac > _Point)
{
stoploss = NormalizeDouble(frac+brokerSpread* _Point+iATR( symbol, period, atrperiod, 1)*atrlevel, _Digits);
break;
}
}
if((MathRound( (OrderStopLoss( )-stoploss) /_Point) != 0)||(OrderStopLoss( )<_Bid))
if(!OrderModify( OrderTicket( ), OrderOpenPrice( ), stoploss, OrderTakeProfit( ),OrderExpiration( ), Red))
Print("OrderModify( OP_SELL) error - ", ErrorDescription( GetLastError( ))); 
}
}else
Print("OrderSelect( ) error - ", ErrorDescription( GetLastError()));
// TrailingStop

bt = iTime(symbol, period, 0);
if(_send_ok) {
_long = false;
_short = false;
}
Comment(cm);
return(0);
}

bool _LCDEA_IsPosition( int type, string symbol, int magic)
{
for(int i=OrdersTotal( )-1; i >= 0; i--)
if(OrderSelect( i, SELECT_BY_POS, MODE_TRADES) ){
if(OrderType( ) == type)
if(OrderSymbol( ) == symbol)
if(OrderMagicNumber () == magic)
return(true) ;
}else
Print("OrderSelect( ) error - ", ErrorDescription( GetLastError()));
return(false) ;
}

double _tp(int type, string symbol, int takeprofit)
{
if(type == OP_BUY)
if(takeprofit > 0)
return(MarketInfo( symbol, MODE_BID)+takeprofit*MarketInfo(symbol, MODE_POINT)) ;
else
return(0.0);
else if(type == OP_SELL)
if(takeprofit > 0)
return(MarketInfo( symbol, MODE_ASK)-takeprofit*MarketInfo(symbol, MODE_POINT)) ;
else
return(0.0);
}

double _nv(string symbol, double lots){
// Adjust trade volume to broker. Take into account minimum & maximum position size.
double step = MarketInfo(symbol, MODE_LOTSTEP) ;
double min = MarketInfo(symbol, MODE_MINLOT) ;
double max = MarketInfo(symbol, MODE_MAXLOT) ;
if(max > 0)
if(lots > max)
return(max);
if(step > 0)
double result = MathRound(lots/ step)*step;
else
result = 0;
if(result < min)
if(min>0)
return(min);
else
return(lots) ;
else if(result > 0)
return(result) ;
else
return(lots) ;
}

#include <stderror.mqh>

int _OrderSend(string symbol, int cmd, double lots, double price, int slippage, double stoploss,
                double takeprofit, string comment, int magic, datetime expiration, color cl)
{
int ticket = OrderSend(symbol, cmd, lots, price, slippage, stoploss, takeprofit, comment, magic, expiration, cl);
if(ticket < 0){
int err = GetLastError( );
Print("ERROR OrderSend #",err,": ", ErrorDescription( err));
}
return(ticket) ;
}

bool _OrderClose( int ticket, double lots, double price, int slippage, color cl=CLR_NONE)
{
bool result = OrderClose(ticket, lots, price, slippage, cl);
if(!result){
int err = GetLastError( );
Print("ERROR OrderClose #",err,": ", ErrorDescription( err));
}
return(result) ;
}

//+--------- --------- --------- --------- --------- --------- ----+
//| Calculate optimal lot size |
//+--------- --------- --------- --------- --------- --------- ----+
double LotsOptimized( )
{
double lot=Lots;
int orders=HistoryTotal(); // history orders total
int losses=0; // number of losses orders without a break
//---- select lot size
lot=NormalizeDouble (AccountFreeMargin()*MaximumRisk /1000.0,1) ;
//---- calcuulate number of losses orders without a break
if(DecreaseFactor> 0)
{
for(int i=orders-1;i>=0;i--)
{
if(OrderSelect( i,SELECT_BY_POS,MODE_HISTORY)==false)
 { Print("Error in history!"); break; }
if(OrderSymbol( )!=Symbol( ) || OrderType()> OP_SELL) continue;
//----
if(OrderProfit( )>0) break;
if(OrderProfit( )<0) losses++;
}
if(losses>1) lot=NormalizeDouble (lot-lot*losses/DecreaseFactor,1) ;
}
//---- return lot size
if(lot<0.01) lot=0.01;
return(lot);
}


