//+------------------------------------------------------------------+
//| 20_MA_Cloud_v1_00.mq5                                          |
//| Draws a two-color cloud between a fast and a slow moving average.|
//+------------------------------------------------------------------+
#property copyright "FXおもしろラボ"
#property version   "1.00"
#property strict
#property description "Two-color cloud between fast and slow moving averages."

#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots   3

#property indicator_label1 "MA Cloud"
#property indicator_type1  DRAW_FILLING
#property indicator_color1 clrCrimson,clrRoyalBlue

#property indicator_label2 "Fast MA"
#property indicator_type2  DRAW_LINE
#property indicator_color2 clrCrimson
#property indicator_width2 2

#property indicator_label3 "Slow MA"
#property indicator_type3  DRAW_LINE
#property indicator_color3 clrRoyalBlue
#property indicator_width3 2

input int                InpFastPeriod   = 12;            // 短期MA期間
input int                InpSlowPeriod   = 26;            // 長期MA期間
input ENUM_MA_METHOD     InpMAMethod     = MODE_EMA;      // MA方式
input ENUM_APPLIED_PRICE InpAppliedPrice = PRICE_TYPICAL; // 適用価格

double g_cloud_fast[];
double g_cloud_slow[];
double g_fast_line[];
double g_slow_line[];

int g_fast_handle = INVALID_HANDLE;
int g_slow_handle = INVALID_HANDLE;

int OnInit()
{
   if(InpFastPeriod < 1 || InpSlowPeriod < 1 || InpFastPeriod >= InpSlowPeriod)
   {
      Print("MA Cloud: periods must satisfy 1 <= fast < slow.");
      return INIT_PARAMETERS_INCORRECT;
   }

   bool buffers_ok = true;
   if(!SetIndexBuffer(0, g_cloud_fast, INDICATOR_DATA)) buffers_ok = false;
   if(!SetIndexBuffer(1, g_cloud_slow, INDICATOR_DATA)) buffers_ok = false;
   if(!SetIndexBuffer(2, g_fast_line, INDICATOR_DATA)) buffers_ok = false;
   if(!SetIndexBuffer(3, g_slow_line, INDICATOR_DATA)) buffers_ok = false;
   if(!buffers_ok)
   {
      PrintFormat("MA Cloud: SetIndexBuffer failed, error=%d", GetLastError());
      return INIT_FAILED;
   }

   ArraySetAsSeries(g_cloud_fast, false);
   ArraySetAsSeries(g_cloud_slow, false);
   ArraySetAsSeries(g_fast_line, false);
   ArraySetAsSeries(g_slow_line, false);

   for(int plot = 0; plot < 3; ++plot)
      PlotIndexSetDouble(plot, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, InpSlowPeriod - 1);
   PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, InpSlowPeriod - 1);
   PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, InpSlowPeriod - 1);

   ResetLastError();
   g_fast_handle = iMA(_Symbol, _Period, InpFastPeriod, 0, InpMAMethod, InpAppliedPrice);
   g_slow_handle = iMA(_Symbol, _Period, InpSlowPeriod, 0, InpMAMethod, InpAppliedPrice);
   if(g_fast_handle == INVALID_HANDLE || g_slow_handle == INVALID_HANDLE)
   {
      PrintFormat("MA Cloud: iMA handle creation failed, error=%d", GetLastError());
      return INIT_FAILED;
   }

   IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
   IndicatorSetString(
      INDICATOR_SHORTNAME,
      StringFormat("MA Cloud (%d,%d,%s)", InpFastPeriod, InpSlowPeriod, EnumToString(InpMAMethod))
   );
   return INIT_SUCCEEDED;
}

void OnDeinit(const int reason)
{
   if(g_fast_handle != INVALID_HANDLE)
   {
      IndicatorRelease(g_fast_handle);
      g_fast_handle = INVALID_HANDLE;
   }
   if(g_slow_handle != INVALID_HANDLE)
   {
      IndicatorRelease(g_slow_handle);
      g_slow_handle = INVALID_HANDLE;
   }
}

int OnCalculate(
   const int rates_total,
   const int prev_calculated,
   const datetime &time[],
   const double &open[],
   const double &high[],
   const double &low[],
   const double &close[],
   const long &tick_volume[],
   const long &volume[],
   const int &spread[]
)
{
   if(rates_total < InpSlowPeriod)
      return 0;
   if(BarsCalculated(g_fast_handle) < rates_total || BarsCalculated(g_slow_handle) < rates_total)
      return 0;

   ResetLastError();
   const int fast_copied = CopyBuffer(g_fast_handle, 0, 0, rates_total, g_fast_line);
   const int slow_copied = CopyBuffer(g_slow_handle, 0, 0, rates_total, g_slow_line);
   if(fast_copied != rates_total || slow_copied != rates_total)
   {
      PrintFormat(
         "MA Cloud: CopyBuffer expected=%d fast=%d slow=%d error=%d",
         rates_total,
         fast_copied,
         slow_copied,
         GetLastError()
      );
      return 0;
   }

   int start = InpSlowPeriod - 1;
   if(prev_calculated > 0 && prev_calculated <= rates_total && prev_calculated - 1 > start)
      start = prev_calculated - 1;
   if(prev_calculated == 0)
   {
      ArrayInitialize(g_cloud_fast, EMPTY_VALUE);
      ArrayInitialize(g_cloud_slow, EMPTY_VALUE);
   }
   for(int i = start; i < rates_total; ++i)
   {
      g_cloud_fast[i] = g_fast_line[i];
      g_cloud_slow[i] = g_slow_line[i];
   }
   return rates_total;
}
