Demo-OptiBot





<expert>
  type=EXPERT_ADVISOR
</expert>
#header#
//+------------------------------------------------------------------+
//|                 Based on the Marketeer's OptiBot Expert Template |
//|                 Copyright © 2009, Marketeer, All Rights Reserved |
//+------------------------------------------------------------------+
#property copyright "#copyright# and Marketeer"
#property link      "#link#"

// TODO: Change magic number
#define MAGIC 0

// TODO: specify actual number of parameters for optimization
#define _PARAMNUM_ 3

#define OPCODE_BUY 1
#define OPCODE_SELL -1
#define OPCODE_BOTH 0
#define OPCODE_EXITBUY 2
#define OPCODE_EXITSELL -2

#extern_variables#

extern string OrdersGroup = "[Orders Settings]";
extern double Lots        = 0.1;
extern int    MinStopLoss = 300;  // used to override min StopLoss values, if they assigned by indicator's signal
extern int    StopLoss    = 0;    // -1 for minimal allowed
extern int    TakeProfit  = 0;    // -1 for twice as stoploss
extern int    Slippage = 3;
extern int    StepOutPoints = 0;  // nonzero means that 2 controorders will be open (a lock), -1 - eq to stoploss by default
extern bool   TrailStops = false;
/*extern*/int TrailingStep = 5;

extern string ParametersGroup = "[Algorithm Parameters]";
extern bool BarByBar = true;

extern string InicatorGroup = "[Indicator Settings]";
// TODO: Add indicator parameters
// NOTE! Their values may change by OptimaticLib during execution
extern int P1 = 0;
extern int P2 = 0;
extern int P3 = 0;

// TODO: These are variables for storage of initial values of indicators' parameters (used in experts capable of running with AND without OptimaticLib)
int DefP1, DefP2, DefP3;

extern string MMGroup = "[Money Management]";
extern bool IncrementLots = false;
extern double MaximumLot = 0.4;
// TODO: Add other Money Management staff

extern string ColoursGroup = "[Colours]";
extern color  clOpenBuy     = LightBlue;
extern color  clOpenSell    = LightCoral;
extern color  clModifyBuy   = RoyalBlue;
extern color  clModifySell  = DeepPink;

#include <OptimaticLib.mq4>

double CurrentLot = 0.1;

int Count = 1;
int OrderBuy = 0;
int OrderSell = 0;
int SignalCode = 0;
int LossThroughCounter = 0;

datetime LastBar = 0;

bool BuySignal;
bool SellSignal;
bool BuyExitSignal;
bool SellExitSignal;

void CheckSignals()
{
  BuySignal = false;
  SellSignal = false;
  BuyExitSignal = false;
  SellExitSignal = false;
  
  static bool bSkipPeriod = false;
  
  if(UseOptimapic)
  {
    // if it's a planned day for optimization - start optimization
    if(optilibistime())
    { 
      // TODO:
      // if too many losses occured, we can enforce re-optimization
      // then we should say to optilib that current params are bad and must be elimineted from next run
      // optilibbanlastresults();
      
      // otherwise, reset banned parameters to no
      optilibbanlastresults(true);
      
      optilibstart();
      double RetParams[_PARAMNUM_];
      optilibgetresults(RetParams);
      // if results are significant - use them
      if(RetParams[0] > 0 && RetParams[1] > 0 && RetParams[2] > 0)
      {
        // TODO: store new parameters in external variables
        P1 = RetParams[0];
        P2 = RetParams[1];
        P3 = RetParams[2];
        bSkipPeriod = false;
      }
      else
      {
        Print("No good parameters at ", TimeToStr(Time[0]));
        bSkipPeriod = true;
      }
    }
  
    if(bSkipPeriod) return;
  }

  OptimaticCallback(0, BuySignal, SellSignal, BuyExitSignal, SellExitSignal);
}

// Here goes a block of callbacks, which are called from OptimaticLib

// produce signals
void OptimaticCallback(int bar, bool &_BuySignal, bool &_SellSignal, bool &_BuyExitSignal, bool &_SellExitSignal)
{
  // TODO: add your code here, invoke indicators
  
  // F(P1 P2 P3)
  // ... _BuySignal = true;
  // ... _BuyExitSignal = true;

  // ... _SellSignal = true;
  // ... _SellExitSignal = true;
}

// return inital parameters for optimization
void OptimaticOnInitParams(double &Params[])
{
  Params[0] = DefP1;
  Params[1] = DefP2;
  Params[2] = DefP3;
}

// assign parameters new values from OptimaticLib (suggested after optimization)
void OptimaticOnSetParams(double InParams[])
{
  P1 = Params[0];
  P2 = Params[1];
  P3 = Params[2];
}

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{
  // remember inital values given by a human
  DefP1 = P1;
  DefP2 = P2;
  DefP3 = P3;
  optilibinit(_PARAMNUM_);
  return(0);
}

//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
{
  return(0);
}

//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
{
  CheckSLTP();
  
  if(TrailStops)
  {
    ModifyOrders(StopLoss);
  }

  if(BarByBar)
  {
    if(LastBar == Time[0]) return;
  }

  LastBar = Time[0];
  
  CheckSignals();
  
  if(StopLoss == -1)
  {
    StopLoss = MarketInfo(Symbol(), MODE_STOPLEVEL) + MarketInfo(Symbol(), MODE_SPREAD);
  }
  
  if(StopLoss > 0 && StopLoss < MinStopLoss) StopLoss = MinStopLoss;
  
  if(TakeProfit == -1) TakeProfit = StopLoss * 2;

  if(OrderBuy > 0 && BuyExitSignal)
  {
    SetOrders(OPCODE_EXITBUY, SignalCode);
  }
  if(OrderSell > 0 && SellExitSignal)
  {
    SetOrders(OPCODE_EXITSELL, SignalCode);
  }

  if(StepOutPoints != 0 && BuySignal && SellSignal)
  {
    if(SetOrders(OPCODE_BOTH, SignalCode) > 0)
    {
      Count++;
    }
  }

  if(BuySignal && !BuyExitSignal)
  {
    if(SetOrders(OPCODE_BUY, SignalCode) > 0)
    {
      Count++;
    }
  }
  if(SellSignal && !SellExitSignal)
  {
    if(SetOrders(OPCODE_SELL, SignalCode) > 0)
    {
      Count++;
    }
  }
  
  return(0);
}
//+------------------------------------------------------------------+

bool OrderMagicCheck()
{
  if(OrderMagicNumber() > MAGIC && OrderMagicNumber() <= MAGIC+2) return(true);
  return(false);
}

void CheckSLTP()
{
  bool bBought = false;
  bool bSold = false;
  for(int i=0; i < OrdersTotal(); i++)
  {
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
      if(OrderMagicCheck())
      {
        if(OrderType() == OP_BUY)
        {
          if(OrderTicket() != OrderBuy)
          {
            // error
            if(OrderBuy == 0) OrderBuy = OrderTicket();
          }
          bBought = true;
          
          if(OrderSell != 0)
          {
            if(OrderSelect(OrderSell, SELECT_BY_TICKET, MODE_TRADES))
            {
              if(OrderType() == OP_SELLSTOP)
              {
                OrderDelete(OrderSell);
                OrderSell = 0;
              }
            }
          }
        }
        else
        if(OrderType() == OP_SELL)
        {
          if(OrderTicket() != OrderSell)
          {
            // error
            if(OrderSell == 0) OrderSell = OrderTicket();
          }
          bSold = true;

          if(OrderBuy != 0)
          {
            if(OrderSelect(OrderBuy, SELECT_BY_TICKET, MODE_TRADES))
            {
              if(OrderType() == OP_BUYSTOP)
              {
                OrderDelete(OrderBuy);
                OrderBuy = 0;
              }
            }
          }
        }
        else
        if(OrderType() == OP_BUYSTOP)
        {
          bBought = true;
        }
        else
        if(OrderType() == OP_SELLSTOP)
        {
          bSold = true;
        }
      }
    }
  }
  
  if(!bBought)
  {
    if(OrderBuy > 0)
    {
      if(OrderSelect(OrderBuy, SELECT_BY_TICKET, MODE_HISTORY))
      {
        if(OrderProfit() < 0 && OrderCloseTime() != 0)
        {
          LossThroughCounter++;
          Print("loss:", LossThroughCounter);
        }
        else
        {
          LossThroughCounter = 0;
          Print("PROFIT");
        }
      }
    }
    OrderBuy = 0;
  }
  if(!bSold)
  {
    if(OrderSell > 0)
    {
      if(OrderSelect(OrderSell, SELECT_BY_TICKET, MODE_HISTORY))
      {
        if(OrderProfit() < 0 && OrderCloseTime() != 0)
        {
          LossThroughCounter++;
          Print("loss:", LossThroughCounter);
        }
        else
        {
          LossThroughCounter = 0;
          Print("PROFIT");
        }
      }
    }
    OrderSell = 0;
  }
}

void ModifyOrders(int DistanceSet)
{
  int    Spread = MarketInfo(Symbol(), MODE_SPREAD);
  int SLMarket = MarketInfo(Symbol(), MODE_STOPLEVEL);

  if(OrderBuy == 0 && OrderSell == 0) return;
  
  if(DistanceSet > 0 && DistanceSet < SLMarket + Spread)
  {
    DistanceSet = SLMarket + Spread;
    if(DistanceSet < MinStopLoss)
    {
      DistanceSet = MinStopLoss;
    }
  }

  for(int i = 0; i < OrdersTotal(); i++)
  {
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
      if(OrderMagicCheck())
      {
        if(OrderSymbol() == Symbol() && OrderStopLoss() > 0)
        {
          if(OrderType() == OP_BUY)
          {
            if(Bid - OrderOpenPrice() > DistanceSet*Point) // only move SL if its new position means profit
            {
              if(OrderStopLoss() < Bid - (DistanceSet + TrailingStep)*Point)
              {
                if(OrderStopLoss() < Bid - (DistanceSet)*Point)
                  OrderModify(OrderTicket(), OrderOpenPrice(), Bid - (DistanceSet)*Point, OrderTakeProfit(), 0, clModifyBuy);
              }
            }
          }
          else
          if(OrderType() == OP_SELL)
          {
            if(OrderOpenPrice() - Ask > DistanceSet*Point) // only move SL if its new position means profit
            {
              if(OrderStopLoss() > Ask + (DistanceSet + TrailingStep)*Point)
              {
                if(OrderStopLoss() > Ask + (DistanceSet)*Point)
                  OrderModify(OrderTicket(), OrderOpenPrice(), Ask + DistanceSet*Point, OrderTakeProfit(), 0, clModifySell);
              }
            }
          }
        }
      }
    }
  }
}

string GetCommentForOrder(int op, int SignalType)
{
  // TODO: use custom prefix for your orders
  return("??-" + GetNameOP(op) + SignalType + "-" + Count);
}

string GetNameOP(int op)
{
  switch(op)
  {
    case OP_BUY      : return("Buy");
    case OP_SELL     : return("Sell");
    case OP_BUYLIMIT : return("BuyLimit");
    case OP_SELLLIMIT: return("SellLimit");
    case OP_BUYSTOP  : return("BuyStop");
    case OP_SELLSTOP : return("SellStop");
    default          : return("Unknown");
  }
}

bool AdjustLevels(int DistanceSet, int SLMarket, int Spread, int &StopLoss, int &TakeProfit)
{
  if(DistanceSet > 0 && DistanceSet < SLMarket)
  {
    Print("The distance ", DistanceSet, " is less than minimal allowed by market ", SLMarket);
    return(false);
  }
  
  if(StopLoss == -1) StopLoss = SLMarket + Spread;
  
  if(StopLoss > 0 && StopLoss < SLMarket + Spread)
  {
    Print("Error! Stoploss ", StopLoss, " is less than allowed by market ", SLMarket, " and spread ", Spread);
    return(false);
  }
  
  if(TakeProfit == -1) TakeProfit = StopLoss*2;

  if(TakeProfit > 0 && TakeProfit < SLMarket + Spread)
  {
    Print("Error! Takeprofit ", TakeProfit, " is less than allowed by market ", SLMarket, " and spread ", Spread);
    return(false);
  }
  return(true);
}

bool OrderSelectLastMagic()
{
  int n = OrdersHistoryTotal();
  for(int i = n-1; i >= 0; i--)
  {
    if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
    {
      if(OrderMagicCheck())
      {
        return(true);
      }
    }
  }
  return(false);
}

double GetLot()
{
  if(!IncrementLots) return(Lots);
  
  int i, n = OrdersHistoryTotal();
  if(n > 0)
  {
    if(OrderSelectLastMagic())
    {
      if(OrderProfit() < 0)
      {
        Print("Loss in previous order, increase lot size");
        CurrentLot += Lots;
        if(CurrentLot > MaximumLot)
        {
          Print("Maximum lot exceeded, reset lot size");
          CurrentLot = Lots;
        }
      }
      else
      {
        Print("Profit in previous order, reset lot size");
        CurrentLot = Lots;
      }
    }
    else
    {
      Print("Error in select last history order");
      CurrentLot = Lots;
    }
  }
  else
  {
    CurrentLot = Lots;
  }
  return(CurrentLot);
}

int SetOrder(int op, int SignalType, double pp, double ldStop, double ldTake, int mn)
{
  color  clOpen;
  string lsComm = GetCommentForOrder(op, SignalType);

  if(op == OP_BUY || op == OP_BUYSTOP) clOpen = clOpenBuy;
  else if(op == OP_SELL || op == OP_SELLSTOP) clOpen = clOpenSell;
  else
  {
    Print("Unsupposed operation. Order will not be set.");
    return(0);
  }
  
  datetime dt = TimeCurrent() + Period()*60*30;

  double pa = Ask;
  double pb = Bid;
  Print("Ask=", pa, " Bid=", pb, " sy=", OrderSymbol(), " op=" + GetNameOP(op), " pp=", pp, " sl=", ldStop, " tp=", ldTake);
  
  int ret = OrderSend(Symbol(), op, GetLot(), pp, Slippage, ldStop, ldTake, lsComm, MAGIC + mn, dt, clOpen);
  if(ret == -1)
  {
    int err = GetLastError();
    Print("Error(", err ,") sending order"); //ErrorDescription(err) #include <stdlib.mqh>
  }
  else
  {
    if(op == OP_BUY || op == OP_BUYSTOP) OrderBuy = ret;
    else OrderSell = ret;
  }
  Print("ticket=", ret);
  return(ret);
}

int SetOrders(int Operation, int SignalType)
{
  int ret;
  double ldStop = 0, ldTake = 0;
  int    Spread = MarketInfo(Symbol(), MODE_SPREAD);
  int  SLMarket = MarketInfo(Symbol(), MODE_STOPLEVEL);

  int StepOut;

  if(StepOutPoints == -1)
  {
    StepOut = StopLoss;
  }
  else
  {
    StepOut = StepOutPoints;
  }
  
  double pAsk = Ask + StepOut*Point;
  double pBid = Bid - StepOut*Point;
  
  Print("Setting order on ", StepOut, " ", Operation);
  
  if(!AdjustLevels(StepOut, SLMarket, Spread, StopLoss, TakeProfit))
  {
    Print("Adjustment error");
    return(0);
  }

  if(Operation == OPCODE_EXITBUY && OrderBuy > 0)
  {
    if(OrderSelect(OrderBuy, SELECT_BY_TICKET))
    {
      if(OrderType() < 2)
      {
        OrderClose(OrderBuy, OrderLots(), Bid, Slippage, DarkOrchid);
        OrderSelect(OrderBuy, SELECT_BY_TICKET); // must re-select to get proper OrderProfit
        if(OrderProfit() < 0 && OrderCloseTime() != 0)
        {
          LossThroughCounter++;
          Print("loss:", LossThroughCounter);
        }
        else
        {
          LossThroughCounter = 0;
          Print("PROFIT");
        }
      }
      else
      {
        OrderDelete(OrderBuy);
      }
    }
    OrderBuy = 0;
  }

  if(Operation == OPCODE_EXITSELL && OrderSell > 0)
  {
    if(OrderSelect(OrderSell, SELECT_BY_TICKET))
    {
      if(OrderType() < 2)
      {
        OrderClose(OrderSell, OrderLots(), Ask, Slippage, DarkOrchid);
        OrderSelect(OrderSell, SELECT_BY_TICKET); // must re-select to get proper OrderProfit
        if(OrderProfit() < 0 && OrderCloseTime() != 0)
        {
          LossThroughCounter++;
          Print("loss:", LossThroughCounter);
        }
        else
        {
          LossThroughCounter = 0;
          Print("PROFIT");
        }
      }
      else
      {
        OrderDelete(OrderSell);
      }
    }
    OrderSell = 0;
  }
  
  if(Operation == OPCODE_BUY || Operation == OPCODE_BOTH) // buy
  {
    if(OrderBuy == 0)
    {
      if(StopLoss != 0) ldStop = pAsk - StopLoss*Point;
      else ldStop = 0;
      if(TakeProfit != 0) ldTake = pAsk + TakeProfit*Point;
      else ldTake = 0;
      if(StepOut > 0)
      {
        ret = SetOrder(OP_BUYSTOP, SignalType, pAsk, ldStop, ldTake, 1);
      }
      else
      {
        ret = SetOrder(OP_BUY, SignalType, pAsk, ldStop, ldTake, 1);
      }
    }
    else
    {
      Print("Buy skipped: buy order exists");
    }
  }
  
  if(Operation == OPCODE_SELL || Operation == OPCODE_BOTH) // sell
  {
    if(OrderSell == 0)
    {
      if(StopLoss != 0) ldStop = pBid + StopLoss*Point;
      else ldStop = 0;
      if(TakeProfit != 0) ldTake = pBid - TakeProfit*Point;
      else ldTake = 0;
      if(StepOut > 0)
      {
        ret = SetOrder(OP_SELLSTOP, SignalType, pBid, ldStop, ldTake, 2);
      }
      else
      {
        ret = SetOrder(OP_SELL, SignalType, pBid, ldStop, ldTake, 2);
      }
    }
    else
    {
      Print("Sell skipped: sell order exists");
    }
  }
  
  return(ret);
}





Sample





Analysis



Market Information Used:

Series array that contains open time of each bar


Indicator Curves created:


Indicators Used:



Custom Indicators Used:

Order Management characteristics:

Checks for the total of open orders
It can change open orders parameters, due to possible stepping strategy
Checks for the total of closed orders
It automatically opens orders when conditions are reached
It Closes Orders by itself

Other Features: