これまで、オブジェクト型によるEasyLanguageでプログラムを書いてきました。
システムトレードのストラテジーの最適化を、いちいちチャート分析に反映して行うのは、手間だとは思わないでしょうか?
しかも、銘柄を変えるのもかなり面倒だと思います。
これらを解決する方法が、オブジェクト指向にはあります。
そしてそれは、マネックス証券からマニュアルを出してくれています(もともとは、TradeStation社のもので、それを日本語訳してくれています。一部英語のままですが)。
ですが、その内容はかなり上級者向けで、いきなり見てもさっぱりわかりません。
ということで、ここで分かりやすく解説したいと思います!これを参考に、ご自身で作られたストラテジーの最適化を楽にしてください。
上にも書いた通り、マニュアルも合わせて読むと、理解が進むと思います。
マニュアルは、「EasyLanguage Optimization API 開発者ガイド」で、Google検索すれば一番上に出てくるpdfのことです。(置いてあるページがどこかわからなかったので、お手数ですが検索ください。すみません。。)
↓↓こういうやつです↓↓

それでは、見ていきましょう。

目次
トレーディングアプリで作成しよう
まずひとつ目の壁が何として最適化ツールを作成するかです。
これまでのオブジェクトの例題をやっているとインジケーターなのかと思いきやそうではありません。
また、バックテストだからストラテジーかと思いきやそうでもありません。
ではなにかというと、「トレーディングアプリ」という新しいタイプです。
EasyLanguageの開発画面を開くところは変わりません。
新規作成で「トレーディングアプリ」を選んでください。

「新規TradingApp」が出るので、名前を適当に入れて「OK」を押してください。ここでは、「Optimization API」とします。

プログラムを書こう
それでは、プログラムを書きましょう。元となるプログラムは、マニュアルに載っているものが使えます。
まずは、マニュアルに載っているものをコピーしてみましょう。

inputsデータ
それでは、プログラムを順に解説していきます。
これまでも説明してきた通り、inputs文では、変数を定義しています。
マニュアルに記載のプログラムをそのまま書くと、
Sym(“MSFT”)
となっています。
” “内で銘柄名を指定しているのですが、海外版を日本語訳しているので、銘柄名もMSFT(マイクロソフト)と米株が対象となっています。
日本株の場合は、みなさんご存知の通り、数字で表されているので、たとえば、”7203″などを書きましょう。
次ぎに、
int MinuteInterval(5)
では、足種を設定するために変数を宣言しています。後に、分足での最適化を試みるので、5分足を想定しています。
LastDateとDaysBackで、最適化の期間を設定します。下の画像の設定の場合、2013年9月30日から、90日前の範囲で最適化することになります。
NumDevsStepは、最適化するパラメーターの変化幅を表しています。あるパラメーターをどのように変化させて、最適化をするかを設定しています。
これらはあくまでinput文なので、好きな名前をつけることができます。ご自身にとって分かりやすい名前をつけたらよいでしょう。

メソッド文の記述(イベント・ストラテジーの設定)
各メソッド文を解説していきます。


InitAppメソッド
ここでは、ストラテジーの最適化を開始するためのスタートボタンを作成しています。
これは、文字通り、最適化を始めるボタンの作成をしています。なんのことか分かりにくいかもしれませんが、後に、最適化を実行する時によくわかります。
内容としては特に大したことはなく、どれくらいの大きさのボタンをどの位置に作るかを表しているくらいです。
特に気にせずに、もとの表記のままで問題ありません。
また、このInitAppは、プロパティで、イベントハンドラとして登録しておく必要があります。
以下の画像のように、「プロパティ」で、「AnalysisTechnique」が選択されているのを確認して、「イベント」ボタンをクリックします。
その後、「Initialized」の「Value」欄を「InitApp」に設定してください。
もし、この作業をしないと、スタートボタンが表示されません。

こうすることで、スタートボタンが押されると、
startButton.Click += OnStartButtonClick文により、メソッド「OnStartButtonClick」が実行されます。
OnStartButtonClickメソッド
OnStartButtonClickメソッドは、スタートボタンが押されると、実行されます。
そして、メソッド「StartOptimization」を実行します。このメソッドについては、後述します。
DefineJobメソッド
このメソッド内には、input文で設定した銘柄や足種、最適化を検証する期間や、最適化するストラテジーとそのパラメーターの設定がされています。
vars文の中身はEasyLanguageにおけるおまじないと思ってください。毎回tsoptを書く手間を省くことができます。
security =job.Securities.Addsecurityは、銘柄情報をプログラム上で指定するための文です。このまま書いておきましょう。
以降4行で、最適化を試みる銘柄、足種、期間を設定しています。
strategy = job.Strategies.Addstrategy(“Bollinger Band LE”)で、ストラテジーの設定をしています。
つまり、最適化を試みるストラテジーは「Bollinger Band LE」ですよ。ということです。
この名前は、ストラテジーの名前を入力すればよいです。本サイトで作った「Cross Average」でも良いですし、ご自身で作ったストラテジーでも当然構いません。
必ず、引用符””を忘れないようにしてください。
strategy.ELInputs.OptRange(“NumDevsDN”,1,3,NumDevsStep)
この文章で、最適化をするパラメーターとその変化幅を決めています。
ここでは、「NumDevsDN」を1から3の間で、「NumDevsStep」(0.1)刻みで変化させて、検証してください。ということになります。
つまり、「NumDevsDN」を1.0,1.1,1.2,,,2.9,3.0というように変えていきます。
この「NumDevsDN」はストラテジー「Bollinger Band LE」の中で使われています。
もちろん名前や変数名を間違えて書いていると、正しく実行されないので、注意してください。
これで、ストラテジーの設定ができました。
StartOptimizationメソッド
スタートボタンが押されると、実行されるメソッドです。
DefineJobメソッドも呼んできており、ストラテジーの最適化を実施するメソッドです。
基本的にこのままで問題ありません。
OptProgressメソッド
最適化の進捗度合いを示してくれるメソッドです。
総テスト数に対して、いくつまで終わりましたよというのを示してくれます。
OptDoneメソッド
最適化が問題なく終わったときに、実行されるメソッドで、完了を知らせるように設定しています。
このとき、総当たりの内、最大の利益を示すように指示しています。
OptErrorメソッド
最適化中にエラーが発生したときに実行されます。
エラーが出た箇所を示してくれます。
これらの、「OptProgress」、「OptDone」、「OptError」メソッドは、なくすことはできません。必要ないと感じた方も、記述が必要です。
プログラムコード
これまでで解説したプログラムを下に書いています。これをコピーして使ってもらっても構いません。
ちなみに、まだ解説していない内容(結果の書き出し)もありますが、後に解説します。
using elsystem;
using elsystem.windows.forms;
using elsystem.drawing;
inputs:
Sym("7203"),
int MinuteInterval(5),
LastDate("04/15/2019"),
int DaysBack(90),
NumDevsStep(0.1),
ResultsFile("c:\Optimizaion.csv");
vars:
Form form1(null),
tsopt.Optimizer optimizer(null);
method void InitApp( elsystem.Object sender, elsystem.InitializedEventArgs args )
vars:
Button startButton;
begin
form1 = Form.Create("OptTest", 500, 500);
form1.BackColor = Color.LightGray;
form1.Dock = DockStyle.Right;
startButton = Button.Create("Start Optimization", 120, 30);
startButton.Location(20, 20);
startButton.Click += OnStartButtonClick;
form1.AddControl(startButton);
form1.Show();
end;
method void OnStartButtonClick(elsystem.Object sender, elsystem.EventArgs args)
begin
StartOptimization();
end;
method tsopt.Job DefineJob()
vars:
tsopt.Job job,
tsopt.Security security,
tsopt.Strategy strategy;
begin
job = new tsopt.Job;
security = job.Securities.AddSecurity();
security.Symbol = Sym;
security.Interval.SetMinuteChart(MinuteInterval);
security.History.LastDateString = LastDate;
security.History.DaysBack = DaysBack;
プログラム続き
strategy = job.Strategies.AddStrategy("Bollinger Bands LE");
strategy.ELInputs.OptRange("NumDevsDn", 1, 3, NumDevsStep);
strategy = job.Strategies.AddStrategy("Bollinger Bands SE");
strategy.ELInputs.OptRange("NumDevsUp", 1, 3, NumDevsStep);
return job;
end;
method void StartOptimization()
vars:
tsopt.Job job;
begin
ClearPrintLog;
Print("Starting optimization...");
job = DefineJob();
optimizer = new tsopt.Optimizer;
optimizer.JobDone += OptDone;
optimizer.JobFailed += OptError;
optimizer.ProgressChanged += OptProgress;
optimizer.StartJob(job);
end;
method void OptProgress(Object sender, tsopt.ProgressChangedEventArgs args)
begin
Print("Test ", args.Progress.TestNum.ToString(), " of ",
args.Progress.TestCount.ToString());
Print(" ", args.BestValues.FitnessName, " = ",
args.BestValues.FitnessValue.ToString());
end;
method void OptDone(object sender, tsopt.JobDoneEventArgs args)
begin
Print("Optimization done");
Print("Net Profit = ", args.Results.NetProfit());
args.Results.WriteFile(ResultsFile,",",tsopt.TradeType.AllTrades, tsopt.ResultsRange.all);
end;
method void OptError(Object sender, tsopt.JobFailedEventArgs args)
begin
Print("Optimization Error: ", args.Error.Message);
end;
実際に最適化してみよう
これで、トレーディングアプリが完成したと思います。
他のインジケーターなどと同様に、F3キーで検証するのを忘れないでください。
最適化の前に設定しよう
トレードステーションの「表示」タブから、「EasyLanguage印刷ログ」というのをクリックしてください。

トレードステーションの下の方に、「印刷ログ」というのが出てきたと思います。
先程までPrint文で書いていた内容が、ここに表示されます。
これを表示していないと、最適化の進捗度合いがわかりません。

最適化してみよう
トレードステーションの左の方にある「トレーディングアプリ」をクリックすると、先程作成した「OptimizationAPI」が追加されています。
これをクリックしてください。

「OptimizationAPI」ウィンドウが開くので、「Start Optimization」をクリックしてください。
これが、「InitApp」メソッド内で作成したスタートボタンのことです。
このボタンを押すことで、ストラテジーの最適化が始まります。

「印刷ログ」に、「Starting Optimization」と出て、最適化が始まります。
下の画像で言うと、テストケースは全部で441ケースで、そのうちのいくつめまで来てますよというのが示されています。
また、最大の利益についても書かれています。
最適化が終わると、「Optimization Done」と出ます。
途中でエラーが出ると、エラー文が書かれます。

結果を確認してみよう
最適化が終わったら、結果を確認してみましょう。ですが、最適化の結果はどこをみたらわかるのでしょうか。
実は、このサイトの上の方に記したプログラムコードには、最適化結果を書き出すように指示していました。
その方法を解説します。
最適化結果をファイルに書き出したい
上では説明しませんでしたが、最適化の結果をcsvファイルに書き出すことができます。
inputs文の中で、
ResultsFile(“c:\Optimization.csv”)
のように、書き出すファイルを宣言します。
そして、「OptDone」メソッドで、結果を書き込むように指示します。
つまり、
args.Results.WriteFile(ResultsFile,”,”,tsopt.TradeType.AllTrades,tsopt.ResultsRange.all)
とすれば、csvファイルが作られて、そこに最適化の結果が書き込まれます。
書き込まれた結果は、ストラテジーのバックテストと同じように、利益が大きい順に並んでいます。

このようにプログラムを記述しておけば、最適化の結果一覧を見ることができます。
最適化の結果を確認してみよう
さっそく、「Optimization.csv」ファイルを開いてみましょう。
一番上にあるケースがもっとも利益が大きかったケースです。
下の画像のように、「NumDevsDN」が1.0で、「NumDevsUP」が1.2のときが、もっとも利益が大きく、「150,360円」であったことがわかります。

これまでの方法でも確認してみよう
この程度のバックテスト・最適化であれば、以前にやったように、チャート分析にストラテジーを挿入して、バックテストおよび最適化ができます。
プログラムが正しいか、確認してみましょう。

結果をみてみると、トレーディングアプリ「OptimizationAPI」の結果と、チャート分析上での最適化の結果で、同じ結果が得られたことから、トレーディングアプリが問題ないことが確認できました。

エラー事例1 トレーディングアプリで作成していない
ここからは、実際に私が直面したエラー事例について書いておきます。
ひとつ目は、トレーディングアプリとして作成せずに、インジケーターとして作成してしまった場合です。
これまでのオブジェクト型のプログラムは、すべてインジケーターとして新規作成していました。
私は、そのときのことが頭に入っており、これもインジケーターで作成するのかと思い込んでいました。(マニュアルにはその辺まで書いてくれていません。)
もし、インジケーターで作成して、チャート分析上で挿入した場合、次のような現象が起こります。
「StartOptimization」というボタンまでは表示されるので、何となくあっているように感じますが、いざ、ボタンを押してみると、以下の画像のようなエラーが返ってきます。
エラー文
「エラー:elsystem.InvalidOperationException: An Optimizer object can only be created within a TradingApp」

いまとなっては、「TradingApp」で作ってね。というのがわかるのですが、当時はさっぱりわかりませんでした。
変に、スタートボタンは表示されるところが、合ってるんじゃないかと思い、混乱していました。
エラー事例2 スタートボタンが表示されない
スタートボタン、「StartOptimization」ボタンが表示されないというエラーもあります。
エラーというか、先に進めないわけですが。
そのときは、「InitApp」をイベントハンドラとして設定できているか確認しましょう。
詳しくは、このサイトの上の、「InitAppメソッド」を確認してください。
さいごに
ストラテジーの最適化を楽に行う方法を紹介しました。
こうすれば、いちいちチャート分析上でストラテジーを挿入しなくても、最適化が可能です。
また、膨大な量の最適化を一気にすることも可能です。
ですが、今回は、スタートボタンだけを作っており、途中で間違いに気付いて止めたくても、止められない状態です。
次回は、スタートボタンだけでなく、ストップボタンを作る方法を紹介します。
その次は、複数銘柄のバックテストをする方法も紹介しようかと思います。

丁寧な説明でありがとうございます。
非常に参考になり助かっております。
この資料の中でわからなかのが
結果確認の『Optimization.csv』がわかりませんでした。
お手数をお掛け致しますが教えた頂けないでしょうか。
宜しくお願い致します。
シケ様
返事が遅くなってしまい、大変申し訳ございません。
『Optimization.csv』は最適化の結果を出力したファイルとなっています。
この記事に書いてある通りに設定していたら、「Cドライブ」の直下に保存されています。
TradeStation内にあるものではありません。
答えになっているでしょうか。
よろしくお願いいたします。
詳しい解説ありがとうございます。とても参考にさせてもらっています。
1つ質問なのですが、csvにて出力されるデータの細かい取引履歴や月ごとの収支を見るように設定するのはどうしたらいいのでしょうか。わかる範囲でお答えいただけると幸いです。
メグ様
コメントありがとうございます!
残念ながら、OptimizationAPIでは細かい取引履歴は参照できないようになっているようです。
https://tradestationjpforum.monex.co.jp/EokpControl?&event=QE0004&tid=13842
例えば、上記の方法では解決できそうです。
ご確認下さい。
返信ありがとうございます。
月ごとの損益をまとめて出すというのでもoptimizationAPIでは難しいのでしょうか。
例えば2019年11月から過去3年間分のバックテストデータを取得したいとして、36ヶ月分ごとの損益を抽出するというのは出来るのでしょか?(1ヶ月×36回をすればできるかと思いますが、まとめて1回でやれる方法があればお聞かせ頂ければと思って質問させてもらいました)
メグ様
OptimizationAPIの場合、すべての計算が終わった後に、書き込み作業が実施されるようです。
つまり、1ヶ月分の計算をする→書き出す→また1ヶ月分の計算をする→書き込む…ということは、残念ながらできないようです。
また、計算した結果をどこかに格納しておいて、それをまとめて書き出すというのも、厳しいみたいです。
(私ができないだけか??)
できないという回答ばかりで申し訳ございません。
いえいえ!
ご丁寧に回答いただきありがとうございます。やはりポートフォリオマエストロを導入してもらうのが一番てっとり早そうですね。
また、ためになる情報を期待しています!ありがとうございました!
いつも勉強させていただいております。
EL初心者のため頓珍漢な質問でしたらすみません。Start Optimizationボタンを押した際、Starting optimization…
に続き「Optimization Error: 不明なリンクエラーが発生しました」と表示され、それ以降処理が止まってしまうのですが、どのような原因が考えられますでしょうか。
こじこじ様
質問ありがとうございます。
せっかく質問くださったのに申し訳ございませんが、ちょっと心当たりがありません。
こじこじ様のメールアドレス宛に、同様のメールを送付しましたので、差し支えなければ、エラーの出るプログラムを送付いただけないでしょうか。
お手数をお掛けして申し訳ございませんが、よろしくお願い致します。
管理人 のっち
のっち様
数々のご記事大変にありがたく拝見いたしております。
おかげさまで、私も複数銘柄バックテストの勉強にさしかかったところです。
さて、上記「プログラムコード」をコピーさせていただき、コード内容はそのままイベントハンドラ登録だけ行い Start Optimization ボタンをクリックすると「この銘柄名が使用可能なデータはありません」というエラーになります。銘柄名を別のものに変えて実行すると、最後の Net Profit に別の数値が、同じく 1回だけ現れて、直後に同エラー文が表示されます。
お手数をおかけしまして恐縮ですが、何か情報等お有りでしたらでしたらご教示いただけますでしょうか。どうぞよろしくお願いいたします。
[印刷ログ]
Test 0 of 441
All: Net Profit = 0.0
Test 0 of 441
All: Net Profit = 0.0
Test 0 of 441
All: Net Profit = 0.0
Test 0 of 441
All: Net Profit = 0.0
Test 1 of 441
All: Net Profit = 96620.0
Optimization Error: データリクエストの失敗:この銘柄名が使用可能なデータはありません
夏屋様
質問ありがとうございます。
たまにその質問が来ますが、なぜかちょっと待ってみると解決することが多いです。
5/3の21:00までメンテナンスのようですので、それが原因かもしれません。
少し時間を空けて、再度試してみてもらえないでしょうか。
直らなければ、申し訳ございませんが、再度連絡いただけますでしょうか。
すぐに解決できず申し訳ございません。
管理人 のっちより
のっち様
お忙しい中、アドバイスいただきまして誠に恐縮です。ありがとうございます。
時々見かけられるエラーなのですね。他記事コメントを拝見できてなくてすみません。
私もお問い合わせ投稿致しました後に、メンテナンス中であったことに気付きましたが、いま試してみたところ変わりがありませんでした。
もうひとつの心当たりは、私の機器環境が相当に非力なことなんですね。PC はタブレットパソコンで、モバイル向け CPU、メモリ 4GB、インターネット接続は WiMAX というところで、処理能力が不足している可能性も予想しております。
なので今出来ることとして、暫く繰り返し動作させて状況を観察しようと(現時点での取組み対象は ETF なので、複数銘柄はゆっくり勉強して行こうと)思います。
もし何か情報がお有りでしたら、今後ともご教示頂けますと大変にありがたく存じます。私も状況が変わりましたらご報告致します。
以上、先ずは誠にありがとうございます。
夏屋
夏屋様
コメントありがとうございます。
直接問い合わせフォームから来たりするので、他記事コメント見れてなくても、まったく問題ありません。
今見直すと、少し言い方が悪くなってしまってました。。そんなつもりなかったです。すみません。。
今後も不明点あれば、気にせずコメントお待ちしております!
さて、状況がいまだ変わらないとのことでしたので、差し支えなければ、
エラーが出るプログラムを送付いただけないでしょうか。
別途、夏屋様宛に、つい先ほど私の方(nocchi.nochilog@gmail.com)からメールいたしましたので、
それに返信いただく形で送付いただければと思います。
こちらでも同様のエラーが出るかなど検証してみようと思います。
お手数をおかけして申し訳ございませんが、よろしくお願いいたします。
のっちより
のっち様
いえいえ、仰り方が少し悪いとか全然ございません。
只々、ご対応いただき感謝いたしております (^^)。
ただいまファイルを送信させていただきました。
引き続き、どうぞよろしくお願いいたします。
夏屋