ドキュメント

アプリケーション

最終更新日:2020年5月18日(マーク・フリック)

フォース・インデックス・インジケーター

ここでは、StrategyQuant Xに新しいカスタムインジケーターを追加する方法について解説します。SQ3とは異なり、SQXでは、MetaTrader 4/5やTradestationなどの一般的な取引プラットフォームに新しいインジケーターを追加するのと同様に、独自のカスタムインジケーターやビルディングブロックを作成してプログラムを拡張することができます。.

私たちは必要なことのすべてを説明するために、このプロセスを1ステップずつ進めていきます。.

最終的に、StrategyQuantに新しいカスタムインジケーターが追加され、戦略生成用のビルディングブロック一覧にそれを追加できるようになります。.

私たちは〜を使います フォース・インデックス 例を示します。このインジケーターはすでにMetaTraderに組み込まれており、そのソースコードはここにあります: https://www.mql5.com/en/code/8013

インジケーターがチャート上でどのように表示されるかは以下の通りです:

 

SQ Xに新しいインジケーターを追加するには、4つのステップがあります:

  1. 新しい指標ビルディングブロックを追加中
  2. (任意、推奨)MTのデータとSQ Xの新インジケーターのテスト
  3. (任意、推奨)インジケーターに基づいた新しいシグナルブロックの追加
  4. インジケーターブロックの翻訳をターゲットプラットフォームの言語に追加しています

 

ステップ1 – コードエディターでの新しいカスタムインジケーターの作成

まず、コードエディタでインジケータを作成します。StrategyQuantは内部でJavaプログラミング言語を使用しているため、カスタムインジケータはJavaでプログラミングする必要があります。.

MQLコードをそのままStrategyQuantにコピー&ペーストしても、動作しません。インジケーターをJava言語で書き直す必要があります。.

まずコードエディターを開く必要があります:

コードエディターではスニペットの作成、編集、修正ができるため、新しいインジケーター用に新しいスニペットを作成します。.

コードエディターで、トップツールバーの「新規作成」ボタンをクリックします。.

これによりダイアログが開き、新しいスニペットに名前を付けてタイプを選択できるようになります。名前は次のようにします:“フォース・インデックス”そして選択 指標 スニペットタイプとして。.

[OK]をクリックすると、その下に新しいフォルダー「ForceIndex」が作成されます スニペット -> SQ -> ブロック -> インジケーター そして新しいスニペットファイル ForceIndex.java このフォルダに.

StrategyQuantでは、各インジケーターを個別のフォルダに配置するのが慣例となっています。これは、後でそのインジケーター用のシグナルを作成する際、関連するスニペットがすべて同じフォルダにまとめられるようにするためです。.

このアクションにより、ForceIndexインジケーター用の新しいファイルが作成され、エディターで開かれました。インジケーターがクラスであり、すでにいくつかの構造を持っていることが確認できます。.

すべてのインジケーターは IndicatorBlock クラスを継承しており、以下の1つのメソッドを実装する必要があります:

  • OnBarUpdate() – インジケーターの値が計算され、出力バッファの1つに格納されるメソッド。チャート上のすべてのバーに対して呼び出されます。.

ソースコードを確認すれば、いくつかのことに気づくはずです。.

まず、StrategyQuantのスニペットでは、@Parameter、@Output、@BuildingBlockといったアノテーションが頻繁に使用されています。これらのアノテーションは、特定の変数やクラスの特別なプロパティ(その変数がパブリックパラメータや出力値であること、あるいはそのクラスがインジケーターブロックであることなど)を宣言するために使用されます。.

次に、インジケーターを作成してコンパイルしたら、次のようにして他のメソッドやインジケーターから呼び出すことができます。 Indicators.YourIndicator(YourIndicatorParameters). これが、当社の新しいインジケーターがOnBlockEvaluate()メソッド内で呼び出される方法です。.

テンプレートから作成されたデフォルトのインジケータークラスのソースコードを、1ステップずつ見ていきましょう:

package SQ.Blocks.Indicators.ForceIndex; 
 
import com.strategyquant.lib.*; import com.strategyquant.datalib.*; import com.strategyquant.tradinglib.*; 
 
import SQ.Internal.IndicatorBlock;

これは、パッケージの標準的なJava宣言と、自社のクラスで使用する必須クラスのインポートです。.

@BuildingBlock(name="(XXX) ForceIndex ", display="ForceIndex (#Period#)[#Shift#]", returnType = ReturnTypes.Price) 
@Help("ForceIndex のヘルプテキスト")

指定された名前を持つビルディングブロックであることをシステムに伝える、インジケータークラスのアノテーション付き定義。.

  • 名前 フィールドとは、ビルディングブロックを選択する際にUIに表示されるものです。.
  • 表示 フィールドは、パラメータ付きウィザードに表示されるものです。どのパラメータをどこに表示するかを制御できます。
  • 戻り値の型 これはインジケーターの一種であり、このインジケーターがどのような値を算出するかを示しています。これは、StrategyQuantがどのタイプを何と比較すべきかを判断するために使用されます。例えば、CCI(数値を返す)とボリンジャーバンド(価格を返す)を比較することはありません。.

インジケーターが持つことができる戻り値の型は、基本的には3つあります:

  • 価格 – インジケーターは価格を計算し、価格チャート上に表示されます – ボリンジャーバンドや移動平均線などのように。.
  • 番号 – インジケーターは、CCI、RSI、MACDなどのように、自身のチャート上に表示される数値を計算します。.
  • 価格帯 – インディケーターは価格帯(2つの価格の差)を計算します – ATRのようです

他の戻り値の型は、別の種類のビルディングブロックで使用されます。.

私たちのケースでは、ForceIndexは価格チャート上に表示されないため、その戻り値の型はPriceではなくNumberになります。次のステップでこれを変更します。.

@Parameter     public DataSeries Input; 
 
@Parameter(defaultValue = "10", isPeriod = true, minValue=1, maxValue=10000, step=1)     public int Period; 
 
@Output     public DataSeries Value;

以下はインジケーターのパラメータです。すべてのインジケーターが複数の入力パラメータを持つことができますが、テンプレートでは例としてそのうちの2つだけを作成しています。すべてのパラメータには次のように注釈が付けられています。 @パラメータ いくつかの属性を持つことができるアノテーション。.

最初のパラメータは 入力, 、これは指標が計算されるデータシリーズの配列であり、例えば始値、高値、安値、終値などが該当します。.

2番目のパラメータは ピリオド, 通常、指標には算出される期間があります。.

第三の変数は 価値, 注釈が異なることに注意してください 出力. これは、この変数がインジケーターのパラメーターではなく、その出力バッファーであることを意味します。インジケーターには通常、出力バッファーが1つしかありませんが、複数のバッファーを持つこともできます。たとえば、ボリンジャーバンドには上限と下限のバッファーがあります。.

隠しパラメータがもう一つあります シフト – これはすべてのインジケーターにデフォルトで含まれており、どの過去の値を参照すべきかを取引エンジンに伝えます。通常、このパラメータを気にする必要はなく、自動的に使用されます。.

次に、一つの方法があります:

protected void OnBarUpdate() {...}

ここはインジケーターの値が計算されるメソッドです。各バーに対してSQから内部的に呼び出され、このバーのインジケーターの値を計算して出力バッファに保存する必要があります。.

これは標準インディケーターテンプレートのソースコードです。次のステップでは、ForceIndexインディケーターを実装するために加えるべき変更点を示します。.

 

ステップ2:生成されたデフォルトテンプレートの修正とインディケーターの実装

ステップ1で作成したインディケーターは標準的なインディケーターのテンプレートであり、まだForceIndexを計算していません。ForceIndexを実装するには、いくつかの作業を行う必要があります:

 

@BuildingBlocks アノテーションを更新する

このインジケーターのアノテーションを以下のように更新します。

@BuildingBlock(name="(FI) ForceIndex", display="ForceIndex (#Nbr_Periods#, #Multiplier)[#Shift#]", returnType = ReturnTypes.Number)

ここは一番簡単な部分です。更新するだけです 名前 インジケーターの(下記を参照して)実際の新しいパラメータを追加する 表示 属性.

また、このインジケーターは独立したチャートに表示される数値を計算するものであり、特定の価格値を出力するわけではないため、returnTypeもNumberに変更しました。.

 

フォースインデックスのパラメータを定義する

最初のステップは少し厄介で、デフォルトの型を変更しなければなりません。 入力 パラメータ。標準テンプレートでは次のように定義されています:

@Parameter public DataSeries Input;

これはパラメータ名です 入力, 、タイプ付きで データシリーズ. これは、1つの価格のみから計算される大部分のインジケーターに当てはまります。例えば、CCIやRSIなどのインジケーターは通常、終値から計算されます。別の価格(例えば始値など)から計算するように設定することも可能ですが、それでも価格配列は1つだけです。.

DataSeries型は、終値、始値、あるいは典型価格などの値を保持する値型の配列です。.
しかし、ForceIndexのMQLソースコードを見ればわかるように、その値は価格のいずれかと出来高から計算されています。.

複数の価格配列に一度にアクセスできるようにするために、出力には別の型を使用します:

@Parameter public ChartData Chart;


チャートデータ
typeはチャート全体を表すオブジェクトであり、指定されたチャート内の始値、高値、安値、終値、出来高の価格にアクセスできます。.


簡単なメモ – 入力データ変数に適した型の選択:
指標が1つの価格から計算される場合は、DataSeriesを使用します。.
複数の価格(例えば高値、安値、終値など)から計算される場合は、ChartDataを使用してください。.

それからPeriodパラメータがありますが、これもそのままで構いません。

@Parameter(defaultValue="10", isPeriod=true, minValue=2, maxValue=1000, step=1) public int Period; 

第3引数は移動平均の計算方法です:

@Parameter(name="Method", defaultValue="0") @Editor(type=Editors.Selection, values="Simple=0,Exponential=1,Smoothed=2,Linear weighted=3") public int MAMethod;

これはもう少し複雑です。なぜなら、このパラメータの編集コントロールとして選択リスト(コンボボックスコントロール)を定義しているからです。そのため、ウィザードで編集する際、ユーザーは定義済みの値から選択できるようになります。.

最後のパラメータは適用価格です。移動平均の計算に使用される価格を指定します。

@Parameter(defaultValue="0") @Editor(type=Editors.Selection, values="Close=0,Open=1,High=2,Low=3,Median=4,Typical=5,Weighted=6") public int AppliedPrice;

当社では、いくつかの属性を使用していることに注意してください。 @パラメータ 注釈

  • デフォルト値 このパラメータのデフォルト値を設定する
  • 期間である=true は SQ に対してこのパラメータが期間であることを伝えます。これらは特殊な方法で処理されます。ビルダーの設定で期間の最小値と最大値を設定できるため、SQ はどのパラメータが期間である知る必要があります。.
  • 最小値、最大値、ステップ ランダム生成プロセス中にこのパラメータに対して生成される最小値と最大値です。.

フォース・インデックスの出力を定義する

ForceIndexインジケーターには出力が1つしかないため、こちらも変更せずにそのままにしておくことができます:

@Output public DataSeries Value;

注釈 出力 これはこのインジケーターの出力バッファであることを意味します。DataSeries型であるため、倍精度浮動小数点数(double)の値の配列であることに注意してください。.

OnBarUpdate() メソッドを実装する

ForceIndexのMQLコードを見れば、それが非常にシンプルであることがわかるでしょう。そのMQLコードは以下の通りです:

int start() {    
  int nLimit;
  int nCountedBars=IndicatorCounted(); 

  //---- insufficient data    
  if(Bars<=ExtForcePeriod) return(0); 

  //---- last counted bar will be recounted    
  if(nCountedBars>ExtForcePeriod) nCountedBars--;    
  nLimit=Bars-nCountedBars; 

  //---- Force Index counted    
  for(int i=0; i<nLimit; i++)       
    ExtForceBuffer[i] = Volume[i] * (iMA(NULL,0,ExtForcePeriod,0,ExtForceMAMethod,ExtForceAppliedPrice,i) - iMA(NULL,0,ExtForcePeriod,0,ExtForceMAMethod,ExtForceAppliedPrice,i+1)); 

  //---- done    
  return(0);   
}

アルゴリズムを分析すると、特定のローソク足におけるフォース・インデックスの値は次のように計算されることがわかります:

ForceIndex[i] = Volume[i] *(MovAvg(Period, MAMethod, AppliedPrice)[i] – MovAvg(Period, MAMethod, AppliedPrice)[i-1])
[i+1]

 

Javaでは次のように実装できます:

protected void OnBarUpdate() throws TradingException {
    DataSeries computedFrom = Chart.getSeries(AppliedPrice); 
 
    double indiValue = Chart.Volume.get(0) * (Indicators.MA(computedFrom, Period, MAMethod).Value.get(0) - Indicators.MA(computedFrom, Period, MAMethod).Value.get(1)); 
 
    Value.set(0, indiValue);     
} 

この場合、指標は非常に単純であり、その計算にはStrategyQuantで実質的に1行だけで済みます。.

私たちはまず、指標を計算するための価格を取得します – 呼び出しによって Chart.getSeries(AppliedPrice).
次に、現在と過去の価格の平均の差に現在の出来高を乗算して、新しいインジケーター値を計算します。.

 

これで全部です。さあ、私たちが打つ時は コンパイル そしてSQを再起動すると、Random Indicators Signalsセクションに新しいForceIndexインジケーターが表示されます。.

当社の新しいインジケーターの完全なソースコード:

package SQ.Blocks.Indicators.ForceIndex;

import com.strategyquant.lib.*;
import com.strategyquant.datalib.*;
import com.strategyquant.tradinglib.*;

import SQ.Internal.IndicatorBlock;

/**
 * UI上に表示されるインジケーター名とその戻り値の型。
 * 可能な戻り値の型:
 * ReturnTypes.Price - SMAやボリンジャーバンドなど、価格チャート上に描画されるインジケーター。
 * ReturnTypes.Price - CCI、RSI、MACDのように、インジケーターが別のチャート上に描画される。
 * ReturnTypes.PriceRange - ATRのように、インジケーターが価格範囲を表す。
 */
@BuildingBlock(name="(FI) ForceIndex ", display="ForceIndex (#Period#)[#Shift#]", returnType = ReturnTypes.Number)
@Help("ForceIndex ヘルプテキスト")
public class ForceIndex extends IndicatorBlock {

  @Parameter
  public ChartData Chart;

  @Parameter(defaultValue="10", isPeriod = true, minValue=2, maxValue=1000, step=1)
  public int Period;

  @Parameter(name="Method", defaultValue="0")
  @Editor(type=Editors.Selection, values="Simple=0,Exponential=1,Smoothed=2,Linear weighted=3")
  public int MAMethod;

  @Parameter(defaultValue="0")
  @Editor(type=Editors.Selection, values="Close=0,Open=1,High=2,Low=3,Median=4,Typical=5,Weighted=6")
  public int AppliedPrice;

  @Output
  public DataSeries Value;

  //------------------------------------------------------------------------
  //------------------------------------------------------------------------
  //------------------------------------------------------------------------

  /**
   * このメソッドは各バーの更新時に呼び出され、ここでインジケータの値が計算されます。
   *
   * MT4とは異なり、ループ内で複数のバーのインジケーター値を計算するのではなく、
   * 最新の(現在の)バーについてのみ値を計算する必要があります。
   * トレーディングエンジンが、チャート内のすべてのバーに対してこのメソッドを呼び出す処理を行います。
   *
   * インジケーター値が計算される実際のバーは、CurrentBar変数に格納されています。
   * 0の場合は、チャートの最初のバーであることを意味します。
   */
  @Override
  protected void OnBarUpdate() throws TradingException {
        double indiValue;

    	indiValue = Chart.Volume.get(0) * (Indicators.MA(Chart.Close, Period, MAMethod).Value.get(0) - Indicators.MA(Chart.Close, Period, MAMethod).Value.get(1));

      	Value.set(0, indiValue);
  }

}

この記事は参考になりましたか? この記事は役に立った この記事は役に立たなかった

5 コメント
最古の
最新 最も投票された
ピーター・コッツェー
ピーター・コッツェー
2020年6月21日 午前8:56

こんにちは。上記のコードをそのままコピーしたのですが、コンパイル時に2つのエラーが発生します。どちらも55行目にあり、同じ説明が表示されます。1つは54列目で、もう1つは114列目です:
シンボルが見つかりません シンボル: メソッド MA(com.strategyquant.datalib.Dataseries,int,int) 場所: タイプ SQ>Internal.Indicators の変数 Indicators
 

最終編集:Pieter Kotzee(6年前)
tomas262
tomas262
返信する  ピーター・コッツェー
2020年6月29日 午後10:06

MA法はパックに含まれていません。こちらからご覧ください https://strategyquant.com/codebase/forceindex/

エマニュエル2
2021年9月21日 午後7:37

ありがとうございます、この例はとても役に立っています

マシュー・ノウリス
2022年2月26日 午後7:09

Force IndexインジケーターとシグナルブロックのJavaコードを無事に追加することができました。エラーなく正常にコンパイルされています。しかし、StrategyQuantでこのインジケーターを使用してストラテジーを生成しようとすると、(MT4、MT5、疑似コードなどの)コードテンプレートが見つからないというエラーが発生します。ストラテジーのコードには次のように表示されています:

エラー!ストラテジーで使用されている1つ以上のブロックが(MT4、MT5、疑似コード等で)実装されていません

テンプレートの読み込みに失敗しました (のため パラメータ値 “blocks/ForceIndex.tpl”):
テンプレートが見つかりません のため 名前 “PseudoCode/blocks/ForceIndex.tpl”.
その名前は次のように解釈された: これ TemplateLoader: MultiTemplateLoader(loader1 = FileTemplateLoader(baseDir=“C:\StrategyQuantX\internal\extend\Code”), loader2 = FileTemplateLoader(baseDir=“C:\StrategyQuantX\user\extend\Code”)).

—-
FTL スタック トレース (“〜” (巣作りに関する):
    – 失敗箇所: #include “blocks/” + blockKey + “.tpl”  [ テンプレート “PseudoCode/pseudoBlocks.inc”  マクロ “printBlock” 行で 122,、列 20]
    – 経由地: @printBlock ブロック?children[0]、シフト [ テンプレート “PseudoCode/pseudoBlocks.inc”  マクロ “printBlock” 行で 107,、列 9]
    – 到達経路:@printBlock c, shift [ テンプレート “PseudoCode/pseudoBlocks.inc”  マクロ “printBlockChild” 行で 148,、列 14]
    – 経由元: @printBlockChild ブロック、, “「#Left#」”  [ テンプレート “PseudoCode/blocks/IsGreater.tpl” 行で 1,、列 2]
    – アクセス方法:#include “blocks/” + blockKey + “.tpl”  [ テンプレート “PseudoCode/pseudoBlocks.inc”  マクロ “printBlock” 行で 122,、列 20]
    – 経由地: @printBlock ブロック?children[0]、シフト [ テンプレート “PseudoCode/pseudoBlocks.inc”  マクロ “printBlock” 行で 107,、列 9]
    – 経由地: @printBlock ブロック [ テンプレート “PseudoCode/blocks/AND.tpl” 行で 5,、列 38]
    – アクセス方法:#include “blocks/” + blockKey + “.tpl”  [ テンプレート “PseudoCode/pseudoBlocks.inc”  マクロ “printBlock” 行で 122,、列 20]
    – 経由地: @printBlock ブロック?children[0]、シフト [ テンプレート “PseudoCode/pseudoBlocks.inc”  マクロ “printBlock” 行で 107,、列 9]
    …(あった 18 もっと、隠された のため tersenes) (Hidden 4 “〜” 行 のため 簡潔さ

それぞれの戦略コード言語のコードテンプレートを追加するにはどうすればよいですか?

tomas262
管理者
返信する  マシュー・ノウリス
2022年2月28日 午後1:53

代わりにこのページからパッケージをインポートしてみてください https://strategyquant.com/codebase/forceindex/

疑似コードとMT4は実装されており、テスト時に正常に動作しています。