//+------------------------------------------------------------------+
//|                                                          MT4.mqh |
//|                        Copyright 2012, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2012, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#include <Trade\Trade.mqh>

//+------------------------------------------------------------------+
//| defines                                                          |
//+------------------------------------------------------------------+
#define MODE_MINLOT 23
#define MODE_POINT 11
#define MODE_ASK 10
#define MODE_BID 9
#define MODE_DIGITS 12
#define MODE_MAXLOT 25

#define OP_BUY 0
#define OP_SELL 1
#define SELECT_BY_TICKET 0
#define SELECT_BY_POS 1
#define MODE_TRADES 0
//+------------------------------------------------------------------+
//| DLL imports                                                      |
//+------------------------------------------------------------------+
// #import "user32.dll"
//   int      SendMessageA(int hWnd,int Msg,int wParam,int lParam);
// #import "my_expert.dll"
//   int      ExpertRecalculate(int wParam,int lParam);
// #import
//+------------------------------------------------------------------+
//| EX5 imports                                                      |
//+------------------------------------------------------------------+
// #import "stdlib.ex5"
//   string ErrorDescription(int error_code);
// #import
//+------------------------------------------------------------------+
double MarketInfo(string symb, int mode)
{
   switch(mode)
   {
      case MODE_MINLOT:
         return(SymbolInfoDouble(symb,SYMBOL_VOLUME_MIN));
         break;
      case MODE_MAXLOT:
         return(SymbolInfoDouble(symb,SYMBOL_VOLUME_MAX));
      case MODE_POINT:
         return(SymbolInfoDouble(symb,SYMBOL_POINT));
         break;
      case MODE_ASK:
         return(SymbolInfoDouble(symb,SYMBOL_ASK));
         break;
      case MODE_BID:
         return(SymbolInfoDouble(symb,SYMBOL_BID));
         break;
      case MODE_DIGITS:   
         return(double(SymbolInfoInteger(symb,SYMBOL_DIGITS)));
      default:
         return(-1);
   }
}
double GetDigitAdjustFactor(string symb)
{
   double info;
   
   info=MarketInfo(symb,MODE_DIGITS);
   if(info==3 || info==5)
      return(10);
   return(1);   
}
string DoubleToStr(double val, int precision)
{
   return(DoubleToString(val,precision));
}

double iHigh(string symb, ENUM_TIMEFRAMES thePeriod, int shift)
{
   MqlRates rates[];

   ZeroMemory(rates);
   ArraySetAsSeries(rates,true);
   CopyRates(symb,thePeriod,shift,1,rates);
   return(rates[0].high);

}
double iLow(string symb, ENUM_TIMEFRAMES thePeriod, int shift)
{
   MqlRates rates[];

   ZeroMemory(rates);
   ArraySetAsSeries(rates,true);
   CopyRates(symb,thePeriod,shift,1,rates);
   return(rates[0].low);

}
void RefreshRates()
{

}
int StrToInteger(string theString)
{
   return(int(StringToInteger(theString)));
}

int OrderSend(string symbol, int cmd, double volume, double price, int slippage, double stoploss, double takeprofit, string comment=NULL, int magic=0, datetime expiration=0, color arrow_color=CLR_NONE) 
{
   MqlTradeRequest  request;      // Anforderungsstruktur 
   MqlTradeResult   result;
   ENUM_ORDER_TYPE type;
   
   double tp=0,sl=0;
   string cmnt;
   
   ZeroMemory(request);
   ZeroMemory(result);
   if(cmd==OP_BUY)
      type=ORDER_TYPE_BUY;
   else if(cmd==OP_SELL)
      type=ORDER_TYPE_SELL;
   else
      return(0);   
   volume=MathMax(volume,MarketInfo(symbol,MODE_MINLOT));
   cmnt=comment;
   request.action=TRADE_ACTION_DEAL;
   request.magic = magic;
   request.symbol=symbol;
   request.volume=volume;
   request.price=NormalizeDouble(price,int(MarketInfo(symbol,MODE_DIGITS)));
   request.deviation=int(MarketInfo(symbol,MODE_POINT));
   request.type=type;
   request.type_filling=ORDER_FILLING_FOK;
   request.comment=cmnt;
   ResetLastError();
   if(OrderSend(request,result))
   {
      PositionSelect(symbol);
      if(takeprofit>0 || stoploss>0)
      {
         Sleep(1000);
         if(PositionSelect(symbol))
         {
            ZeroMemory(request);
            ZeroMemory(result);
            price=PositionGetDouble(POSITION_PRICE_OPEN);
            if(type==ORDER_TYPE_BUY)
            {
               if(takeprofit>0)
                  tp=price+takeprofit*MarketInfo(symbol,MODE_POINT)*GetDigitAdjustFactor(symbol);
               if(stoploss>0)
                  sl=price-stoploss*MarketInfo(symbol,MODE_POINT)*GetDigitAdjustFactor(symbol);
            }
            else
            {
               if(takeprofit>0)
                  tp=price-takeprofit*MarketInfo(symbol,MODE_POINT)*GetDigitAdjustFactor(symbol);
               if(stoploss>0)
                  sl=price+stoploss*MarketInfo(symbol,MODE_POINT)*GetDigitAdjustFactor(symbol);
            }
            request.action=TRADE_ACTION_SLTP;
            request.symbol=symbol;
            request.tp=NormalizeDouble(tp,int(MarketInfo(symbol,MODE_DIGITS)));
            request.sl=NormalizeDouble(sl,int(MarketInfo(symbol,MODE_DIGITS)));
            while(!OrderSend(request,result))
               Sleep(1000);
         }      
      } 
   }
   return(int(PositionGetInteger(POSITION_IDENTIFIER)));
}

bool OrderSelect( int index, int select, int pool=MODE_TRADES) 
{
   string symb="xxx";
   int i;
   
   if(select==SELECT_BY_POS)
   {
      symb=PositionGetSymbol(index);
   }
   else if(select==SELECT_BY_TICKET)
   {
      for(i=0;i<PositionsTotal();i++)
      {
         OrderSelect(i,SELECT_BY_POS);
         if(PositionGetInteger(POSITION_IDENTIFIER)==index)
         {
            symb=PositionGetSymbol(i);
            break;   
         }
      }   
   }
   return(PositionSelect(symb));
}

int OrderTicket()
{
   return(int(PositionGetInteger(POSITION_IDENTIFIER)));
}
double OrderOpenPrice()
{
   return(PositionGetDouble(POSITION_PRICE_OPEN));
}
string OrderSymbol()
{
   return(PositionGetString(POSITION_SYMBOL));
}
string OrderComment()
{
   return(PositionGetString(POSITION_COMMENT));
}
int OrderMagicNumber()
{
   return(int(PositionGetInteger(POSITION_MAGIC)));
}
int OrderType()
{
   return(int(PositionGetInteger(POSITION_TYPE)));
}
double OrderProfit()
{
   return(PositionGetDouble(POSITION_PROFIT));
}
double OrderSwap()
{
   return(PositionGetDouble(POSITION_SWAP));
}
double OrderCommission()
{
   return(PositionGetDouble(POSITION_COMMISSION));
}
double OrderLots()
{
   return(PositionGetDouble(POSITION_VOLUME));
}
bool OrderClose(int ticket, double lots, double price, int slippage, color Color=CLR_NONE) 
{
   CTrade trade;
   string symb;
   
   if(OrderSelect(ticket,SELECT_BY_TICKET))
   {
      trade.PositionClose(OrderSymbol(),ULONG_MAX);
      if(!OrderSelect(ticket,SELECT_BY_TICKET))
         return(true);
      
   }
   return(false);
}
