Functions: iAO and iAC

 

Hi people!

I wanted to create a custom Awesome Oscillator (B. Williams) and also Accelerator Oscillator. Does this look correct? Can anyone check, test or suggest any improvement to it? I got to the point where I do not have improvements to it, such as speed or even error-checking (btw, it has none just right now :P)

// Awesome Oscillator (custom)
int iMyAO(
   string             ao_symbol=_Symbol,            // symbol name
   ENUM_TIMEFRAMES    ao_timeframes=PERIOD_CURRENT, // base period
   int                ao_fast_period=5,             // fast period
   int                ao_slow_period=34,            // slow period
   int                ao_shift=0,                   // horizontal shift
   ENUM_MA_METHOD     ao_ma_method=MODE_SMA,        // moving average method
   ENUM_APPLIED_PRICE ao_applied_price=PRICE_MEDIAN // applied price (typical = (H+L)/2
)
{
   double ao_fast = iMA(ao_symbol,ao_timeframes,ao_fast_period,ao_shift,ao_ma_method,ao_applied_price); // smoothing
   double ao_slow = iMA(ao_symbol,ao_timeframes,ao_slow_period,ao_shift,ao_ma_method,ao_applied_price); // baseline
   return(ao_fast-ao_slow); //AO = SMA5 - SMA34 ( standard awesome oscillator uses midpoint = (H+L)/2 )
};

// Acceleration Oscillator (custom)
int iMyAC(
   string             ac_symbol=_Symbol,            // symbol name
   ENUM_TIMEFRAMES    ac_timeframes=PERIOD_CURRENT, // base period
   int                ac_fast_period=5,             // fast period
   int                ac_slow_period=34,            // slow period (>fastperiod)
   int                ac_shift=0,                   // horizontal shift
   ENUM_MA_METHOD     ac_ma_method=MODE_SMA,        // moving average method
   ENUM_APPLIED_PRICE ac_applied_price=PRICE_MEDIAN // applied price
   )
{
   ac_ao          = iMyAO(ac_symbol,ac_timeframes,ac_fast_period,ac_shift,ac_ma_method,ac_applied_price);
   ac_ao_baseline = iMA  (ac_symbol,ac_timeframes,ac_fast_period,ac_shift,ac_ma_method,ac_applied_price);
   return(ac_ao_smoothed-ac_ao_baseline); // AO(5,34) - iMA(AO,5)
};
 
Arthur Albano:

Hi people!

I wanted to create a custom Awesome Oscillator (B. Williams) and also Accelerator Oscillator. Does this look correct? Can anyone check, test or suggest any improvement to it? I got to the point where I do not have improvements to it, such as speed or even error-checking (btw, it has none just right now :P)

The following line does not look correct:

ac_ao_baseline = iMA  (ac_symbol,ac_timeframes,ac_fast_period,ac_shift,ac_ma_method,ac_applied_price);
 
#include <Expert\Expert.mqh>

CExpert  ExtExpert;
CTrade   ExtTrade;

input string               Expert_Title = "EA_Envelopes";         // Expert Name
input ulong                Expert_MagicNumber = 295;              // Magic Number
input bool                 Expert_EveryTick =true;                // Every Tick
input ushort               inp_ea_bars_back = 0;                  // EA: Backward Price [bars]
input ushort               inp_env_ma_period = 14;                // Envelopes: Periods [bars]
input ushort               inp_env_ma_shift = 0;                  // Envelopes: Shift [bars]
input ushort               inp_env_distance_pips = 20;            // Envelopes: Distance [pips]
input ENUM_MA_METHOD       inp_env_ma_method = MODE_SMA;          // Envelopes: MA Method [enum]
input ENUM_APPLIED_PRICE   inp_env_applied_price = PRICE_MEDIAN;  // Envelopes: Applied Price [enum]
input ushort               inp_ac_ma_fast_period = 5;             // Accelerator: Fast Period [bars]
input ushort               inp_ac_ma_slow_period = 34;            // Accelerator: Slow Period [bars]
input ushort               inp_ac_ma_shift = 0;                   // Accelerator: Shift [bars]
input ENUM_MA_METHOD       inp_ac_ma_method = MODE_SMA;           // Accelerator: MA Method [enum]
input ENUM_APPLIED_PRICE   inp_ac_applied_price = PRICE_MEDIAN;   // Accelerator: Applied Price [enum]
input ushort               inp_ea_lots = 1;                       // Initial lots
input ushort               inp_ea_stoploss = 20;                  // EA: Stoploss [pips]
input ushort               inp_ea_takeprofit = 20;                  // EA: Takeprofit [pips]

void OnInit()
{
//--- Initializing expert
   if(!ExtExpert.Init(Symbol(),Period(),Expert_EveryTick,Expert_MagicNumber))
     {
      //--- failed
      printf(__FUNCTION__+": error initializing expert");
      ExtExpert.Deinit();
     }
     
}


void OnTick()
{
   // Create a Price Array
   MqlRates PriceInformation[];
   
   // Sort it from current candles to oldest candle
   ArraySetAsSeries(PriceInformation,true);
   
   // Copy the price data into the array
   int Data=CopyRates(Symbol(),Period(),0,Bars(Symbol(),Period()),PriceInformation);
   
   // create arrays for several prices
   double UpperBandArray[];
   double LowerBandArray[];
   double FastMovingAverage[];
   double SlowMovingAverage[];
   double AwesomeOscillator[];
   double AcceleratorOscillator[];
   
   ArraySetAsSeries(UpperBandArray,true);
   ArraySetAsSeries(LowerBandArray,true);
   ArraySetAsSeries(FastMovingAverage,true);
   ArraySetAsSeries(SlowMovingAverage,true);
   ArraySetAsSeries(AwesomeOscillator,true);
   ArraySetAsSeries(AcceleratorOscillator,true);

   // pips to percent
   double ext_env_deviation = (inp_env_distance_pips*SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE)/inp_env_applied_price)/100;
   
   // handles
   int EnvelopesDefinition = iEnvelopes(_Symbol,_Period,inp_env_ma_period,inp_env_ma_shift,inp_env_ma_method,inp_env_applied_price,ext_env_deviation);
   int FastMovingAverageDefinition = iMA(_Symbol,_Period,inp_ac_ma_fast_period,inp_ac_ma_shift,inp_ac_ma_method,inp_ac_applied_price);
   int SlowMovingAverageDefinition = iMA(_Symbol,_Period,inp_ac_ma_slow_period,inp_ac_ma_shift,inp_ac_ma_method,inp_ac_applied_price);
   
   // Copy prices information into the array
   CopyBuffer(EnvelopesDefinition,0,0,inp_ea_bars_back+2,UpperBandArray);
   CopyBuffer(EnvelopesDefinition,1,0,inp_ea_bars_back+2,LowerBandArray);
   CopyBuffer(FastMovingAverageDefinition,0,0,inp_ac_ma_slow_period,FastMovingAverage);
   CopyBuffer(SlowMovingAverageDefinition,0,0,inp_ac_ma_slow_period,SlowMovingAverage);
   
   ArrayResize(AwesomeOscillator,inp_ac_ma_slow_period);
   
   for (int i=0;i<(inp_ac_ma_fast_period-1);i++)
   {
      AwesomeOscillator[i] = FastMovingAverage[i]-SlowMovingAverage[i];
   };
   
   ArrayResize(AcceleratorOscillator,inp_ac_ma_slow_period);
   
   for (int i=0;i<(inp_ac_ma_fast_period-1);i++)
   {
      double FastAO = 0.0;
      for (int k=0;k<(inp_ac_ma_fast_period-1);k++)
      {
         FastAO =+ AwesomeOscillator[k];
      };
      FastAO = FastAO / inp_ac_ma_fast_period;
      AcceleratorOscillator[i] = AwesomeOscillator[i]-FastAO;
   };

   double env_UpperBandValue=NormalizeDouble(UpperBandArray[0],_Digits);
   double env_LowerBandValue=NormalizeDouble(LowerBandArray[0],_Digits);
   double ac_FastMovingAverageValue=NormalizeDouble(FastMovingAverage[0],_Digits);
   double ac_SlowMovingAverageValue=NormalizeDouble(SlowMovingAverage[0],_Digits);
   double ac_AwesomeOscillatorValue=NormalizeDouble(AwesomeOscillator[0],_Digits);   
   double ac_AcceleratorOscillatorValue=NormalizeDouble(AcceleratorOscillator[0],_Digits);
   
   // Calculate the Ask Price
   double Ask=NormalizePrice(SymbolInfoDouble(_Symbol,SYMBOL_ASK));
   // Calculate the Bid Price
   double Bid=NormalizePrice(SymbolInfoDouble(_Symbol,SYMBOL_BID));
   // Calculate the Bid Price
   double Last=NormalizePrice(SymbolInfoDouble(_Symbol,SYMBOL_LAST));
   // Calculate the Bid Price
   double const TickSize=NormalizePrice(SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE));
   

   // Chart output of the Envelopes
   string ext_env_signal = "hold";
   if (PriceInformation[0].close > env_UpperBandValue) ext_env_signal = "sell";
   if (PriceInformation[0].close < env_LowerBandValue) ext_env_signal = "buy";
   
   // Chart output of the AC
   bool ext_ac_signal = false;
   if (AcceleratorOscillator[0]>AcceleratorOscillator[1]) ext_ac_signal=true;

   Comment ("Price: ",PriceInformation[inp_ea_bars_back].close,"\n",
            "Envelopes: Upper Value: ",NormalizePrice(env_UpperBandValue),"\n",
            "Envelopes: Lower Value: ",NormalizePrice(env_LowerBandValue),"\n",
            "Envelopes: Signal: ",ext_env_signal,"\n",
            "Accelerator: Fast MA: ",NormalizePrice(ac_FastMovingAverageValue),"\n",
            "Accelerator: Slow MA: ",NormalizePrice(ac_SlowMovingAverageValue),"\n",
            "Accelerator: Awesome Oscillator: ",NormalizePrice(ac_AwesomeOscillatorValue),"\n"
            "Accelerator: Accelerator Oscillator: ",NormalizePrice(ac_AcceleratorOscillatorValue),"\n",
            "Accelerator: Signal: ",ext_ac_signal,"\n"
           );
   // Trading
   if (ext_env_signal=="sell" && PositionsTotal()<1 && ext_ac_signal==true)
      ExtTrade.Sell(inp_ea_lots,_Symbol,0,Last+inp_ea_stoploss*TickSize,Last-inp_ea_takeprofit*TickSize);
   if (ext_env_signal=="buy" && PositionsTotal()<1 && ext_ac_signal==true)
      ExtTrade.Buy(inp_ea_lots,_Symbol,0,Last-inp_ea_stoploss*TickSize,Last+inp_ea_takeprofit*TickSize);
   
}

double NormalizePrice(double price)
{
   double m_tick_size = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE);
   return(NormalizeDouble(MathRound(price/m_tick_size)*m_tick_size,_Digits));
}
 
Arthur Albano:

Fully working Expert Advisor with custom Accelerator and Envelopes.

 

Now with trailing:


#include <Trade\AccountInfo.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>
CAccountInfo   ExtAccountInfo;
CTrade         ExtTrade;
CPositionInfo  ExtPositionInfo;
CSymbolInfo    ExtSymbolInfo;
ENUM_POSITION_TYPE         direction;


input string               Expert_Title = "EA_Envelopes";         // EA: Expert Name
input ulong                Expert_MagicNumber = 295;              // EA: Magic Number
input bool                 Expert_EveryTick =true;                // EA: Every Tick
input ushort               inp_ea_bars_back = 0;                  // EA: Backward Price [bars]
input ushort               inp_ea_lots = 1;                       // EA: Initial lots
input ushort               inp_ea_stoploss = 16;                  // EA: Stoploss [pips]
input ushort               inp_ea_trailingstop = 23;              // EA: Trailing Stop [pips]
input ushort               inp_env_ma_period = 26;                // Envelopes: Periods [bars]
input ushort               inp_env_ma_shift = 0;                  // Envelopes: Shift [bars]
input ushort               inp_env_distance_pips = 35;            // Envelopes: Distance [pips]
input ENUM_MA_METHOD       inp_env_ma_method = MODE_SMA;          // Envelopes: MA Method [enum]
input ENUM_APPLIED_PRICE   inp_env_applied_price = PRICE_TYPICAL; // Envelopes: Applied Price [enum]
input ushort               inp_ac_ma_fast_period = 3;             // Accelerator: Fast Period [bars]
input ushort               inp_ac_ma_slow_period = 11;            // Accelerator: Slow Period [bars]
input ushort               inp_ac_ma_shift = 0;                   // Accelerator: Shift [bars]
input ENUM_MA_METHOD       inp_ac_ma_method = MODE_SMA;           // Accelerator: MA Method [enum]
input ENUM_APPLIED_PRICE   inp_ac_applied_price = PRICE_TYPICAL;  // Accelerator: Applied Price [enum]

void OnTick()
{
   ExtSymbolInfo.Name(Symbol());
   PositionSelect(_Symbol);
   MqlDateTime now;
   datetime current_time=TimeCurrent();
   TimeToStruct(current_time,now);
   
   // Create a Price Array
   MqlRates PriceInformation[];
   
   // Sort it from current candles to oldest candle
   ArraySetAsSeries(PriceInformation,true);
   
   // Copy the price data into the array
   int Data=CopyRates(Symbol(),Period(),0,Bars(Symbol(),Period()),PriceInformation);
   
   // create arrays for several prices
   double UpperBandArray[];ArrayInitialize(UpperBandArray,NULL);
   double LowerBandArray[];ArrayInitialize(LowerBandArray,NULL);
   double FastMovingAverage[];ArrayInitialize(FastMovingAverage,NULL);
   double SlowMovingAverage[];ArrayInitialize(SlowMovingAverage,NULL);
   double AwesomeOscillator[];ArrayInitialize(AwesomeOscillator,NULL);
   double AcceleratorOscillator[];ArrayInitialize(AcceleratorOscillator,NULL);
   
   ArraySetAsSeries(UpperBandArray,true);
   ArraySetAsSeries(LowerBandArray,true);
   ArraySetAsSeries(FastMovingAverage,true);
   ArraySetAsSeries(SlowMovingAverage,true);
   ArraySetAsSeries(AwesomeOscillator,true);
   ArraySetAsSeries(AcceleratorOscillator,true);

   // pips to percent
   double ext_env_deviation = (inp_env_distance_pips*SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE)/inp_env_applied_price)/100;
   
   // handles
   int EnvelopesDefinition = iEnvelopes(_Symbol,_Period,inp_env_ma_period,inp_env_ma_shift,inp_env_ma_method,inp_env_applied_price,ext_env_deviation);
   int FastMovingAverageDefinition = iMA(_Symbol,_Period,inp_ac_ma_fast_period,inp_ac_ma_shift,inp_ac_ma_method,inp_ac_applied_price);
   int SlowMovingAverageDefinition = iMA(_Symbol,_Period,inp_ac_ma_slow_period,inp_ac_ma_shift,inp_ac_ma_method,inp_ac_applied_price);
   
   // Copy prices information into the array
   CopyBuffer(EnvelopesDefinition,0,0,inp_ea_bars_back+2,UpperBandArray);
   CopyBuffer(EnvelopesDefinition,1,0,inp_ea_bars_back+2,LowerBandArray);
   CopyBuffer(FastMovingAverageDefinition,0,0,inp_ac_ma_slow_period,FastMovingAverage);
   CopyBuffer(SlowMovingAverageDefinition,0,0,inp_ac_ma_slow_period,SlowMovingAverage);
   
   ArrayResize(AwesomeOscillator,inp_ac_ma_fast_period);
   
   for (int i=0;i<(inp_ac_ma_fast_period-1);i++)
   {
      AwesomeOscillator[i] = FastMovingAverage[i]-SlowMovingAverage[i];
   };
   
   if (ArraySize(AcceleratorOscillator)!= inp_ac_ma_fast_period) ArrayResize(AcceleratorOscillator,inp_ac_ma_fast_period);
   
   for (int i=0;i<(inp_ac_ma_fast_period-1);i++)
   {
      double FastAO = 0.0;
      for (int k=0;k<(inp_ac_ma_fast_period-1);k++)
      {
         FastAO =+ AwesomeOscillator[k];
      };
      FastAO = FastAO / inp_ac_ma_fast_period;
      AcceleratorOscillator[i] = AwesomeOscillator[i]-FastAO;
   };

   double env_UpperBandValue=NormalizeDouble(UpperBandArray[0],_Digits);
   double env_LowerBandValue=NormalizeDouble(LowerBandArray[0],_Digits);
   double ac_FastMovingAverageValue=NormalizeDouble(FastMovingAverage[0],_Digits);
   double ac_SlowMovingAverageValue=NormalizeDouble(SlowMovingAverage[0],_Digits);
   double ac_AwesomeOscillatorValue=NormalizeDouble(AwesomeOscillator[0],_Digits);   
   double ac_AcceleratorOscillatorValue=NormalizeDouble(AcceleratorOscillator[0],_Digits);
   
   // Prices
   double Ask=NormalizePrice(SymbolInfoDouble(_Symbol,SYMBOL_ASK));
   double Bid=NormalizePrice(SymbolInfoDouble(_Symbol,SYMBOL_BID));
   double Last=NormalizePrice(SymbolInfoDouble(_Symbol,SYMBOL_LAST));
   double CurrentStopLoss = Last;
   CurrentStopLoss = (PositionsTotal()==0) ? Last : PositionGetDouble(POSITION_SL);
   double const TickValue=NormalizePrice(SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE));
   // Calculate the size
   double const TickSize=NormalizePrice(SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE));
   

   // Chart output of the Envelopes
   string ext_env_signal = "hold";
   if (PriceInformation[0].close > env_UpperBandValue) ext_env_signal = "sell";
   if (PriceInformation[0].close < env_LowerBandValue) ext_env_signal = "buy";
   
   // Chart output of the AC
   bool ext_ac_signal = false;
   if (AcceleratorOscillator[0]>AcceleratorOscillator[1]) ext_ac_signal=true;

   // Entry
   if (ext_env_signal=="sell" && PositionsTotal()<1 && ext_ac_signal==true && (now.hour < 12))
      ExtTrade.Sell(inp_ea_lots,_Symbol,0,Last+inp_ea_stoploss*TickSize,NULL);
   if (ext_env_signal=="buy" && PositionsTotal()<1 && ext_ac_signal==true && (now.hour < 12))
      ExtTrade.Buy(inp_ea_lots,_Symbol,0,Last-inp_ea_stoploss*TickSize,NULL);
   
   // Trailing
   string MsgTrailing = "no trailing";
   
   if (PositionsTotal()!=0 && (MathAbs(Last-CurrentStopLoss)/TickSize>inp_ea_trailingstop))
      {
         MsgTrailing = "trailing active";
         double NewSL = ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE))==POSITION_TYPE_BUY ? Last-inp_ea_trailingstop*TickSize : Last+inp_ea_trailingstop*TickSize;
         ExtTrade.PositionModify(_Symbol,NewSL,0);
      }

   
   if (PositionsTotal() > 0)
   {
      if (now.hour > 15)
         {
            CloseAllPositions();
         };
   };


   Comment ("Price: ",PriceInformation[inp_ea_bars_back].close,"\n",
            "Envelopes: Upper Value: ",NormalizePrice(env_UpperBandValue),"\n",
            "Envelopes: Lower Value: ",NormalizePrice(env_LowerBandValue),"\n",
            "Envelopes: Signal: ",ext_env_signal,"\n",
            "Accelerator: Fast MA: ",NormalizePrice(ac_FastMovingAverageValue),"\n",
            "Accelerator: Slow MA: ",NormalizePrice(ac_SlowMovingAverageValue),"\n",
            "Accelerator: Awesome Oscillator: ",NormalizePrice(ac_AwesomeOscillatorValue),"\n"
            "Accelerator: Accelerator Oscillator: ",NormalizePrice(ac_AcceleratorOscillatorValue),"\n",
            "Accelerator: Signal: ",ext_ac_signal,"\n",
            "Bid: ", Bid,"\n",
            "Ask: ", Ask,"\n",
            "Last: ", Last,"\n",
            "SL Distance: ",MathAbs(Last-CurrentStopLoss)/TickSize,"\n",
            "Trailing: ",MsgTrailing,"\n"
           );
   
}

double NormalizePrice(double price)
{
   double m_tick_size = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE);
   return(NormalizeDouble(MathRound(price/m_tick_size)*m_tick_size,_Digits));
}

void CloseAllPositions()
{
   for(int i=PositionsTotal()-1;i>=0;i--)
   {
      ulong ticket=PositionGetTicket(i);
      ExtTrade.PositionClose(ticket);
   }
}
Reason: