2017年5月26日金曜日

[Trading View]Pineスクリプト 入門4 計算処理

Trading View Pine Script入門その4です。

スクリプトでインジケータ値を計算する際の勘所をかいておきたいと思います。
Pineでの計算関数一覧みたいなのを期待された方はごめんなさい。Trading View社の日本語化が進むことを期待したいと思います。
(もしくは、やるのでTrading View社さん雇ってくれないかなぁ・・・w)

Trading Viewの計算処理はなれると簡単ですが、変数の扱いが少しだけ特殊です。C系のプログラムをやっている方にとっては、考え方の切り替えが必要になってきます。


まず、呼び出しルールです。
上のチャートの場合、画面にバーが26本見えています。
この場合、スクリプトは26回呼び出されます。

その時、常に描画対象のバーをインデックス0として呼び出されます。
MQLのように昔のバーを描画する際に、forループで回す必要がないのはこのためです。

この制御は、移動平均など、常にバーに対して描画が発生するインジケータの作成をとても簡略化します。
例えば、単純移動平均のスクリプトは、次の通りです。パラメータ入力を含めても5行で終わります。

//@version=3
study("テストスクリプト", overlay = true)
_period = input(21, "Period")
_source = input(close, "Source", type=source)
plot(sma(_source, _period))

ただし、この制御のおかげで、強い制限がかかっている箇所があります。
その説明の前に、変数は配列扱いになっているという部分を見ていきたいと思います。

//@version=3
study("テストスクリプト")
_period = input(21, "Period")
_source = input(close, "Source", type=source)
_sma = sma(_source, _period)
//5本前のデータを参照する
_drawSma = _sma[5]
plot(_sma )
plot(_drawSma , color=red)

_sma = sma(_source, _period)で宣言した(何度も書きますが=は変数宣言構文です)
_sma変数に対して[5]というインデックス参照を行う事で、前のバーの計算結果を見ることができます。実行すると、赤線で5本遅れの移動平均が描画されます。(ちょっとわかりやすくするためにサブチャートとして出しています。)

EMAなど、前のバーの情報を見たい場合は、このテクニックを利用すれば計算可能です。

で、制限なのですが、MT4では普通に過去配列値を変更可能です。Fractalなど、自分のバーからみて未来情報も参照しているような場合、さかのぼって値を変更する制御を行ったりします。

Trading Viewでは、この書き換えという制御に強い制限が入っています。

//@version=3
study("テストスクリプト")
_period = input(21, "Period")
_source = input(close, "Source", type=source)
_sma = sma(_source, _period)
//5本前のデータを参照する
_drawSma = _sma[5]
//過去の書き換えはコンパイルエラーになる
_drawSma[2] := 0.0
plot(_sma )

上記のように、MQLでは普通に見かける書き換えロジックですが、Pine スクリプトでは実現できません。
このため、Zigzagのように書き換え前提となっているインジケータの実装には、手間がかかる事となります。

書き換えが発生しないインジケータは簡単に実装可能だが、過去の書き換えが発生するインジケータはとても手間がかかるということです。


「MT4でFXを勝ち抜く研究をするブログ」で公開している無料インジケータは、こちらの一覧から。
インジケータ一覧

Twitterもよろしくお願いします。
https://twitter.com/mt4program
Trading View プロフィール

ブログランキングにご協力よろしくお願いします。m(._.)m
にほんブログ村 為替ブログ FX テクニカルトレード派へ
にほんブログ村

お約束ですが、本ブログは、投資に対する利益を約束する物ではありません。最終的には自己責任によるご判断よろしくお願いいたします。

2017年5月24日水曜日

[MT4インジケータ]最小二乗法移動平均(LSMA)

#LWMAとLSMA間違えてましたので記事修正

Trading Viewみてたら最小二乗法移動平均(LSMA)ってあるんですね・・・。なんかよさそう。
あれ?MT4になくね?(いえ、探せばフリーインジであるので、わざわざ作る必要ないのですが・・・。)

ということで作ってみました。
指定価格の近似直線を計算して、近似直線の起点から傾き*Lengthを足した値に点を描画するインジケータです。傾きでトレンドの方向、実際の価格位置でトレンドとマッチしているかがわかる感じのようです。


//------------------------------------------------------------------
// 最小二乗法移動平均
#property copyright "Copyright 2017,  Daisuke"
#property link      "http://mt4program.blogspot.jp/"
#property version   "1.00"
#property strict
#property indicator_chart_window

//バッファーを指定する。
#property indicator_buffers 1

//プロット数を指定する。
#property indicator_plots   1

#property indicator_type1   DRAW_LINE
#property indicator_color1  clrAqua
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

input ENUM_APPLIED_PRICE MaPrice = PRICE_CLOSE; // 対象価格

input int Length = 25;  // 長さ
input int Offset = 0;   // オフセット

double lsma[];

//------------------------------------------------------------------
//初期化
int OnInit()
{
   //インジケーターバッファを初期化する。
   int count = 0 ;
   SetIndexBuffer(count++, lsma);

   string short_name = "LSMA";
   IndicatorShortName(short_name);

   return INIT_SUCCEEDED;
}

//------------------------------------------------------------------
//計算イベント
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[])            //スプレット
{
   //LSMA計算式 LSMA = 平均値 + 傾き * (Length - 1 - Offset)
   //左側を0起点とするように計算しないとおかしなことになるので注意
   for( int i = rates_total - prev_calculated - 1; i >= 0 && !IsStopped(); i-- )
   {
      if( i > rates_total - Length - 1 ) continue;
      
      //指定価格の最小二乗平均値を求める
      double sumX = 0;
      double sumY = 0;
      double sigXY = 0;
      double sigX2 = 0;

      for( int j = 0; j < Length; j++ )
      {
         double value = GetPrice(open[i + j], close[i + j], high[i + j], low[i + j], MaPrice);
         
         sumX += (Length - j - 1);
         sumY += value;
         sigXY += (Length - j - 1) * value;
         sigX2 += MathPow((Length - j - 1), 2);
      }
      
      sumX /= Length;
      sumY /= Length;
      double base = (sigX2 - Length * MathPow(sumX, 2));
      
      double a = 0 ;
      double b = 0 ;
      if( base != 0 )
      {
         a = ( sigXY - Length * sumX * sumY) / base;
         b = sumY - a * sumX;
      }
      
      lsma[i] = b + a * (Length - 1 - Offset);
   }
   
   return rates_total - 1;
}

//------------------------------------------------------------------
// 価格を計算する。
// return 対象価格
double GetPrice(
   double open,   // オープン値
   double close,  // クローズ値
   double high,   // 高値
   double low,    // 安値
   ENUM_APPLIED_PRICE maPrice    //取得価格
   )
{
   double price = 0;

   switch( maPrice )
   {
      case PRICE_CLOSE:
         price = close;
         break;
      case PRICE_OPEN:
         price = open;
         break;
      case PRICE_HIGH:
         price = high;
         break;
      case PRICE_LOW:
         price = low;
         break;
      case PRICE_MEDIAN:
         price = (high + low) / 2;
         break;
      case PRICE_TYPICAL:
         price = (high + low + close) / 3;
         break;
      case PRICE_WEIGHTED:
         price = (high + low + close + close) / 4;
         break;
   }
   return price;
}




「MT4でFXを勝ち抜く研究をするブログ」で公開している無料インジケータは、こちらの一覧から。インジケータ一覧

Twitterもよろしくお願いします。
https://twitter.com/mt4program
Trading View プロフィール

ブログランキングにご協力よろしくお願いします。m(._.)m
にほんブログ村 為替ブログ FX テクニカルトレード派へ
にほんブログ村

お約束ですが、本ブログは、投資に対する利益を約束する物ではありません。最終的には自己責任によるご判断よろしくお願いいたします。

[Trading View]Pineスクリプト 入門3 インジケータスクリプトの全体とパラメータ定義

Trading ViewでのPine Scriptです。

次のコードは練習がてらに公開しているGMMAのソースです。

PineスクリプトはMQLのように関数定義を必須としていません。
いきなり処理がスタートします。

//@version=3
study("GMMA", overlay=true)

//inputs
_Period1 = input(3, "EMA1 Period")
_Period2 = input(5, "EMA2 Period")
_Period3 = input(8, "EMA3 Period")
_Period4 = input(10, "EMA4 Period")
_Period5 = input(12, "EMA5 Period")
_Period6 = input(15, "EMA6 Period")
_Period7 = input(30, "EMA7 Period")
_Period8 = input(35, "EMA8 Period")
_Period9 = input(40, "EMA9 Period")
_Period10 = input(45, "EMA10 Period")
_Period11 = input(50, "EMA11 Period")
_Period12 = input(60, "EMA12 Period")


//calculate ema
ema1 = ema(close, _Period1)
ema2 = ema(close, _Period2)
ema3 = ema(close, _Period3)
ema4 = ema(close, _Period4)
ema5 = ema(close, _Period5)
ema6 = ema(close, _Period6)
ema7 = ema(close, _Period7)
ema8 = ema(close, _Period8)
ema9 = ema(close, _Period9)
ema10 = ema(close, _Period10)
ema11 = ema(close, _Period11)
ema12 = ema(close, _Period12)

plot(ema1, color=green, title="short1")
plot(ema2, color=green, title="short2")
plot(ema3, color=green, title="short3")
plot(ema4, color=green, title="short4")
plot(ema5, color=green, title="short5")
plot(ema6, color=green, title="short6")

plot(ema7, color=red, title="long1")
plot(ema8, color=red, title="long2")
plot(ema9, color=red, title="long3")
plot(ema10, color=red, title="long4")
plot(ema11, color=red, title="long5")
plot(ema12, color=red, title="long6")

MQLをやっている人は、あれ?、昔のバーの処理していない??と思われるかもしれません。
Trading Viewのインジケータは、処理としてBar毎に一回呼び出される(最新バーのみTick毎)となるようです。MQLのOnTickのように、すべてのバーに対して計算をするループ文は不要です。Trading Viewの特徴として、見えている範囲のインジケータ値しか生成しません。チャートの縮尺変更が入り新しいバーがチャート上に出現した場合、生成されたバー数分だけこのスクリプトが呼び出される形です。MQLになれた人はOnTick内のforループの中身だけ書くというとわかりやすいでしょうか?

さて、もう少し細かく見ていきたいと思います。まずインジケータパラメータです。
//inputs
_Period1 = input(3, "EMA1 Period")

インジケータパラメータはinput関数で指定します。

上記の例は、
「EMA1 Periodという名前のパラメータの設定結果を_Period1という変数を「宣言」して中身に入れなさい。」
という構文です。(=は変数宣言構文なので注意)

input関数で定義すると、インジケータをチャートにセットした後、設定ボタンを押したときの画面に出てくるようになります。

■GMMAのパラメータ

このinput関数は入力に関する様々な制御が可能です。
型の指定、入力制限などを行えます。あと、インジケータの入力配列などを切り替えも可能です。ちょっとGMMAを修正してみましょう。

//@version=3
study("GMMA", overlay=true)

//inputs
_Source = input(close, "Target Source")
_Period1 = input(3, "EMA1 Period")
_Period2 = input(5, "EMA2 Period")
_Period3 = input(8, "EMA3 Period")
_Period4 = input(10, "EMA4 Period")
_Period5 = input(12, "EMA5 Period")
_Period6 = input(15, "EMA6 Period")
_Period7 = input(30, "EMA7 Period")
_Period8 = input(35, "EMA8 Period")
_Period9 = input(40, "EMA9 Period")
_Period10 = input(45, "EMA10 Period")
_Period11 = input(50, "EMA11 Period")
_Period12 = input(60, "EMA12 Period")


//calculate ema
ema1 = ema(_Source, _Period1)
ema2 = ema(_Source, _Period2)
ema3 = ema(_Source, _Period3)
ema4 = ema(_Source, _Period4)
ema5 = ema(_Source, _Period5)
ema6 = ema(_Source, _Period6)
ema7 = ema(_Source, _Period7)
ema8 = ema(_Source, _Period8)
ema9 = ema(_Source, _Period9)
ema10 = ema(_Source, _Period10)
ema11 = ema(_Source, _Period11)
ema12 = ema(_Source, _Period12)

plot(ema1, color=green, title="short1")
plot(ema2, color=green, title="short2")
plot(ema3, color=green, title="short3")
plot(ema4, color=green, title="short4")
plot(ema5, color=green, title="short5")
plot(ema6, color=green, title="short6")

plot(ema7, color=red, title="long1")
plot(ema8, color=red, title="long2")
plot(ema9, color=red, title="long3")
plot(ema10, color=red, title="long4")
plot(ema11, color=red, title="long5")
plot(ema12, color=red, title="long6")

■計算配列を指定できるようにしたGMMAのパラメータ


input関数の使用例をコメント付きでまとめておきます。

//整数型の入力
_inputInt = input(0, "int type", integer)

//整数値入力の最大最小値指定
_inputIntMinMax = input(0, "int type minmax", type=integer, minval=0, maxval=10)

//整数値入力のステップ指定
_inputIntStep = input(0, "int type step", type=integer, minval=0, maxval=10, step=2)

//整数値入力の入力限定
_inputIntOpt = input(0, "int type opt", type=integer, options=[0, 4, 8])


//浮動小数点型の入力
_inputFloat = input(0, "float type", float)

//浮動小数点入力の最大最小値指定
_inputFloatMinMax = input(0, "float type minmax", type=float, minval=0.0, maxval=2.5)

//浮動小数点入力のステップ指定
_inputFloatStep = input(0, "float type step", type=float, minval=0.0, maxval=2.5, step=0.1)

//浮動小数点入力の入力限定
_inputFloatOpt = input(0, "float type opt", type=float, options=[0.0, 1.5, 3.0])

//論理値
_boolInput = input(true, "bool type", type=bool)

//文字列
_stringInput = input("abc", "string type", type=string)

//文字列の入力制限
_stringInputOpt = input("abc", "string type opt", type=string, options=["abc", "def", "ghi"])

//通貨ペア/株価コード
_symbol = input("EURUSD", "symbol type", type=symbol)

//足の解像度(1時間足とか1日足など) 入力は分単位
_resolutionInput = input(60, "resolution type", type=resolution)

//入力配列(チャートに存在する配列を指定可能)
_sourceInput = input(close, "source type", type=source)

//セッション(時間範囲) hhmm-hhmmで指定する。・・が指定するとインジケータが異常終了する・・・。
//_sessionInput = input("0900-1500", "session type", type=session)

//チャート挿入時、入力必須のパラメータの場合confirm=trueを指定する。
//Pineエディタからチャートの追加ボタンを押した場合は動かない
//チャートコンテキストメニュー→インジケーターの挿入からは有効
_confirm = input(0, "confirm", type=integer, confirm=true)


「MT4でFXを勝ち抜く研究をするブログ」で公開している無料インジケータは、こちらの一覧から。
インジケータ一覧

Twitterもよろしくお願いします。
https://twitter.com/mt4program
Trading View プロフィール

ブログランキングにご協力よろしくお願いします。m(._.)m
にほんブログ村 為替ブログ FX テクニカルトレード派へ
にほんブログ村

お約束ですが、本ブログは、投資に対する利益を約束する物ではありません。最終的には自己責任によるご判断よろしくお願いいたします。