😊

TEMAを自作したい ③ChatGPTはすごい

2024/12/16に公開

選択肢からHMA、THMA、TEMA、EHMAを選択できるようにしました。

これも、自分で書いたものがあったのですが、もっといいコードをさらっと書いてくれるChatGPTさん、様様ですね。

//+------------------------------------------------------------------+
//|                                           HMA THMA TEMA EHMA.mq5 |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#include <MovingAverages.mqh>

//--- indicator settings
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
#property indicator_type1   DRAW_LINE
#property indicator_color1  Red
#property indicator_width1  1

enum ENUM_MA_MODE {
   MODE_HMA,
   MODE_THMA,
   MODE_TEMA,
   MODE_EHMA
};
//--- input parameters
input int            InpMAPeriod=13;         // Period
input int            InpMAShift=0;           // Shift
input ENUM_MA_MODE   InpMAMethod=MODE_HMA;  // Method

//--- indicator buffer
double ExtLineBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit() {
   //--- エラーチェック: 異常な期間を防ぐ
   if (InpMAPeriod < 1) {
      Print("Error: InpMAPeriod must be greater than 0.");
      return INIT_FAILED;
   }

   //--- indicator buffers mapping
   SetIndexBuffer(0, ExtLineBuffer, INDICATOR_DATA);

   //--- sets first bar from what index will be drawn
   int draw_begin = (InpMAMethod == MODE_TEMA) ? 3 * InpMAPeriod - 3 : InpMAPeriod;
   PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, draw_begin);

   //--- sets indicator shift
   PlotIndexSetInteger(0, PLOT_SHIFT, InpMAShift);

   //--- name for indicator label
   string ma_type;
   switch (InpMAMethod) {
   case MODE_TEMA:
      ma_type = "TEMA";
      break;
   case MODE_HMA:
      ma_type = "HMA";
      break;
   case MODE_THMA:
      ma_type = "THMA";
      break;
   case MODE_EHMA:
      ma_type = "EHMA";
      break;
   default:
      ma_type = "Unknown MA";
      break;
   }
   string short_name = StringFormat("%s(%d)", ma_type, InpMAPeriod);
   IndicatorSetString(INDICATOR_SHORTNAME, short_name);
   PlotIndexSetString(0, PLOT_LABEL, short_name);
   
   return INIT_SUCCEEDED;

}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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 < InpMAPeriod) {
      Print("Error: Not enough bars to calculate MA. Ensure rates_total >= InpMAPeriod.");
      return(0);
   }

   //--- MAの種類に応じた計算
   switch (InpMAMethod) {
   case MODE_TEMA:
      CalculateTEMA(close, rates_total, prev_calculated, InpMAPeriod, ExtLineBuffer);
      break;

   case MODE_HMA:
      CalculateHMA(close, rates_total, prev_calculated, InpMAPeriod, ExtLineBuffer);
      break;

   case MODE_THMA:
      CalculateTHMA(close, rates_total, prev_calculated, InpMAPeriod, ExtLineBuffer);
      break;

   case MODE_EHMA:
      CalculateEHMA(close, rates_total, prev_calculated, InpMAPeriod, ExtLineBuffer);
      break;

   default:
      Print("Error: Unsupported MA method selected.");
      return(prev_calculated); // 未対応の種類の場合は何もせず終了
   }

   //--- 計算結果を返す
   return(rates_total);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CalculateTEMA(const double &price[], int rates_total, int prev_calculated, int period, double &buffer[]) {
   if(period < 2 || rates_total < 3 * period - 3) return;

   double ema_buffer[], ema_of_ema_buffer[], ema_of_ema_of_ema_buffer[];
   ArrayResize(ema_buffer, rates_total);
   ArrayResize(ema_of_ema_buffer, rates_total);
   ArrayResize(ema_of_ema_of_ema_buffer, rates_total);
   ArrayInitialize(ema_buffer, 0);
   ArrayInitialize(ema_of_ema_buffer, 0);
   ArrayInitialize(ema_of_ema_of_ema_buffer, 0);

   // 1. 最初のEMA
   ExponentialMAOnBuffer(rates_total, prev_calculated, 0, period, price, ema_buffer);

   // 2. EMA of EMA
   ExponentialMAOnBuffer(rates_total, prev_calculated, period - 1, period, ema_buffer, ema_of_ema_buffer);

   // 3. EMA of EMA of EMA
   ExponentialMAOnBuffer(rates_total, prev_calculated, 2 * period - 2, period, ema_of_ema_buffer, ema_of_ema_of_ema_buffer);

   // 4. TEMAを計算
   for(int i = MathMax(prev_calculated, 2 * period - 2); i < rates_total; i++) {
      buffer[i] = 3 * ema_buffer[i] - 3 * ema_of_ema_buffer[i] + ema_of_ema_of_ema_buffer[i];
   }
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CalculateHMA(const double &price[], int rates_total, int prev_calculated, int period, double &buffer[]) {
   if(period < 2 || rates_total < period) return;

   int half_period = period / 2;
   int sqrt_period = (int)MathRound(MathSqrt(period));

   double lwma_half_buffer[], lwma_full_buffer[], intermediate_buffer[];
   ArrayResize(lwma_half_buffer, rates_total);
   ArrayResize(lwma_full_buffer, rates_total);
   ArrayResize(intermediate_buffer, rates_total);
   ArrayInitialize(lwma_half_buffer, 0);
   ArrayInitialize(lwma_full_buffer, 0);
   ArrayInitialize(intermediate_buffer, 0);

   // 1. LWMA(period / 2)
   LinearWeightedMAOnBuffer(rates_total, prev_calculated, 0, half_period, price, lwma_half_buffer);

   // 2. LWMA(period)
   LinearWeightedMAOnBuffer(rates_total, prev_calculated, 0, period, price, lwma_full_buffer);

   // 3. 中間結果を計算
   for(int i = MathMax(prev_calculated, period); i < rates_total; i++) {
      intermediate_buffer[i] = 2 * lwma_half_buffer[i] - lwma_full_buffer[i];
   }

   // 4. HMAを計算
   LinearWeightedMAOnBuffer(rates_total, prev_calculated, 0, sqrt_period, intermediate_buffer, buffer);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CalculateTHMA(const double &price[], int rates_total, int prev_calculated, int period, double &buffer[]) {
   if(period < 3 || rates_total < period) return;

   int third_period = period / 3;
   int half_period = period / 2;

   double wma_third_buffer[], wma_half_buffer[], wma_full_buffer[], intermediate_buffer[];
   ArrayResize(wma_third_buffer, rates_total);
   ArrayResize(wma_half_buffer, rates_total);
   ArrayResize(wma_full_buffer, rates_total);
   ArrayResize(intermediate_buffer, rates_total);
   ArrayInitialize(wma_third_buffer, 0);
   ArrayInitialize(wma_half_buffer, 0);
   ArrayInitialize(wma_full_buffer, 0);
   ArrayInitialize(intermediate_buffer, 0);

   // 1. WMA(period / 3)
   LinearWeightedMAOnBuffer(rates_total, prev_calculated, 0, third_period, price, wma_third_buffer);

   // 2. WMA(period / 2)
   LinearWeightedMAOnBuffer(rates_total, prev_calculated, 0, half_period, price, wma_half_buffer);

   // 3. WMA(period)
   LinearWeightedMAOnBuffer(rates_total, prev_calculated, 0, period, price, wma_full_buffer);

   // 4. 中間結果を計算
   for(int i = MathMax(prev_calculated, period); i < rates_total; i++) {
      intermediate_buffer[i] = 3 * wma_third_buffer[i] - wma_half_buffer[i] - wma_full_buffer[i];
   }

   // 5. THMAを計算
   LinearWeightedMAOnBuffer(rates_total, prev_calculated, 0, period, intermediate_buffer, buffer);
}
//+------------------------------------------------------------------+
void CalculateEHMA(const double &price[], int rates_total, int prev_calculated, int period, double &buffer[])
{
   if (period < 2 || rates_total < period) return;

   int half_period = period / 2;
   int sqrt_period = (int)MathRound(MathSqrt(period));

   double ema_half_buffer[], ema_full_buffer[], intermediate_buffer[];
   ArrayResize(ema_half_buffer, rates_total);
   ArrayResize(ema_full_buffer, rates_total);
   ArrayResize(intermediate_buffer, rates_total);
   ArrayInitialize(ema_half_buffer, 0);
   ArrayInitialize(ema_full_buffer, 0);
   ArrayInitialize(intermediate_buffer, 0);

   // 1. EMA(period / 2)
   ExponentialMAOnBuffer(rates_total, prev_calculated, 0, half_period, price, ema_half_buffer);

   // 2. EMA(period)
   ExponentialMAOnBuffer(rates_total, prev_calculated, 0, period, price, ema_full_buffer);

   // 3. 中間結果を計算: 2 * EMA(period / 2) - EMA(period)
   for (int i = MathMax(prev_calculated, period); i < rates_total; i++)
   {
      intermediate_buffer[i] = 2 * ema_half_buffer[i] - ema_full_buffer[i];
   }

   // 4. EHMAを計算: EMA(intermediate_buffer, sqrt(period))
   ExponentialMAOnBuffer(rates_total, prev_calculated, 0, sqrt_period, intermediate_buffer, buffer);
}

これをもとに今度は自動売買を作っていきたいと思います。

Discussion