📉
TEMAを自作したい ②ChatGPTはすごい
前回はTEMAで使用されているOnCalculate関数の引数の違いについてみていきました。
実装されていたものは引数が4つでしたが10個のものに書き直そうとしていました。
以下まるっとChatGPTに教えてもらったものです。
以下は、指定されたコードを**形式2(10引数のOnCalculate
関数)**に書き直したバージョンです。この形式では、open[]
, high[]
, low[]
, close[]
, volume[]
など複数のデータを扱えるようになります。
形式2で書き直したTEMA.mq5
//+------------------------------------------------------------------+
//| TEMA.mq5 |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2024, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property description "Triple Exponential Moving Average"
#include <MovingAverages.mqh>
//--- indicator settings
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots 1
#property indicator_type1 DRAW_LINE
#property indicator_color1 DarkBlue
#property indicator_width1 1
#property indicator_label1 "TEMA"
#property indicator_applied_price PRICE_CLOSE
//--- input parameters
input int InpPeriodEMA=14; // EMA period
input int InpShift=0; // Indicator's shift
//--- indicator buffers
double TemaBuffer[];
double Ema[];
double EmaOfEma[];
double EmaOfEmaOfEma[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
void OnInit()
{
//--- indicator buffers mapping
SetIndexBuffer(0,TemaBuffer,INDICATOR_DATA);
SetIndexBuffer(1,Ema,INDICATOR_CALCULATIONS);
SetIndexBuffer(2,EmaOfEma,INDICATOR_CALCULATIONS);
SetIndexBuffer(3,EmaOfEmaOfEma,INDICATOR_CALCULATIONS);
//--- sets first bar from what index will be drawn
PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,3*InpPeriodEMA-3);
//--- sets indicator shift
PlotIndexSetInteger(0,PLOT_SHIFT,InpShift);
//--- name for indicator label
string short_name=StringFormat("TEMA(%d)",InpPeriodEMA);
IndicatorSetString(INDICATOR_SHORTNAME,short_name);
PlotIndexSetString(0,PLOT_LABEL,short_name);
}
//+------------------------------------------------------------------+
//| Triple Exponential Moving Average |
//+------------------------------------------------------------------+
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 < 3 * InpPeriodEMA - 3)
return(0);
int start;
if(prev_calculated == 0)
start = 0; // 初回計算
else
start = prev_calculated - 1; // 以前の計算から続けて実行
//--- 終値を利用してEMAを計算
ExponentialMAOnBuffer(rates_total, prev_calculated, 0, InpPeriodEMA, close, Ema);
//--- EMA(Ema)の値を用いて、2段階目のEMAを計算
ExponentialMAOnBuffer(rates_total, prev_calculated, InpPeriodEMA - 1, InpPeriodEMA, Ema, EmaOfEma);
//--- 3段階目のEMAを計算
ExponentialMAOnBuffer(rates_total, prev_calculated, 2 * InpPeriodEMA - 2, InpPeriodEMA, EmaOfEma, EmaOfEmaOfEma);
//--- TEMAを計算
for(int i = start; i < rates_total && !IsStopped(); i++)
TemaBuffer[i] = 3 * Ema[i] - 3 * EmaOfEma[i] + EmaOfEmaOfEma[i];
//--- 計算完了、次回の計算位置を返す
return(rates_total);
}
//+------------------------------------------------------------------+
変更点と解説
1. 引数の変更
-
OnCalculate
関数を形式2(10引数)に変更しました。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[])
- 元の
price[]
をclose[]
に置き換えています。 -
open[]
,high[]
,low[]
,volume[]
など、追加のデータを利用する場合に対応可能。
- 元の
2. 価格データの選択
- 元の
price[]
の代わりにclose[]
を使用。ExponentialMAOnBuffer(rates_total, prev_calculated, 0, InpPeriodEMA, close, Ema);
- 必要に応じて、
open[]
やhigh[]
などに変更可能。
- 必要に応じて、
3. 柔軟性の向上
- 形式2を採用したことで、
open[]
,high[]
,low[]
,tick_volume[]
など複数のデータを必要とするインジケータに発展させる基盤を整備。
4. オリジナルコードの構造を維持
- TEMAの計算フロー(3段階のEMAを計算して結果を組み合わせる)をそのまま維持。
使用例
形式2の利点を活かす方法
-
高値と安値の平均でTEMAを計算する:
double hl2[rates_total]; for(int i = 0; i < rates_total; i++) hl2[i] = (high[i] + low[i]) / 2.0; ExponentialMAOnBuffer(rates_total, prev_calculated, 0, InpPeriodEMA, hl2, Ema);
-
ティックボリュームに基づく分析を追加:
for(int i = start; i < rates_total && !IsStopped(); i++) if(tick_volume[i] > 1000) // 高ボリューム時に特定の処理を実行 TemaBuffer[i] = 3 * Ema[i] - 3 * EmaOfEma[i] + EmaOfEmaOfEma[i];
まとめ
- 形式2(10引数)を使用することで、
close[]
以外のデータにもアクセスでき、柔軟なインジケータ作成が可能になります。 - この修正版では、オリジナルのTEMA計算フローを維持しつつ、
close[]
を用いたシンプルな実装となっています。 - 必要に応じて
high[]
やlow[]
を使ったカスタマイズにも対応可能です。
ちゃんと出力できました。
もうなんだか、考えることをやめてしまいそうですね、、、
Discussion