この記事では、XMの取引口座の設定から始まり、MetaTrader 4 (MT4) の基本操作、プログラミングの基礎、EA(エキスパートアドバイザー)の開発に至るまで、FXの自動売買に必要な知識と技術を学べます。
開発環境の設定:XMトレーディングで口座開設
XMは2009年に設立され、世界196カ国でサービスを展開し、日本人投資家からも高い信頼を得ています。
XM口座の開設
XMのメリット
- 安心の実績: 2009年設立以来、世界中でサービスを提供。
- 高レバレッジ: 最大1000倍までのレバレッジを提供。
- 豊富な取扱商品: 50種類以上のFX通貨ペア、仮想通貨、貴金属、株式指数など。
- MT4/MT5対応: パソコン、スマートフォン、タブレットで利用可能。
- 日本語サポート: 日本語でのヘルプセンターや問い合わせ対応があり。
- ゼロカットシステム: 口座がマイナスになった場合でも追証なしでゼロリセット。
- 豊富なボーナス: 新規登録で最大13,000円分の取引ボーナス、入金ボーナスも。
XMでの口座開設方法
- XMの公式サイトにアクセス: 公式サイトから口座開設ページに進みます。
- 個人情報の入力: 氏名、住所、電話番号、メールアドレスなどを入力。
- 取引口座の設定: 取引プラットフォーム(MT4/MT5)と口座タイプを選択。
- 口座開設の完了: 入力した情報を確認し、口座開設を完了します。
入出金方法
- 入金: クレジットカード、電子決済サービス、銀行送金など多様な方法で即時入金可能。
- 出金: 出金要求を行うと、迅速に処理されます。出金方法は入金時と同様です。
トレードの始め方
- プラットフォームのダウンロード: MT4またはMT5をダウンロードし、インストールします。
- ログイン: XMから提供されるIDとパスワードを使用してログインします。
- チャートの設定: チャート表示をカスタマイズし、分析に必要なインジケーターを設定します。
- 取引実施: 取引したい通貨ペアを選択し、注文を出してトレードを開始します。
開発環境の設定:MT4画面の見方
MT4はXM公式サイトのプラットフォームからダウンロードすることができます。指示に従ってクリックしていくだけで、簡単に使えるようになります。
MT4のダウンロード
MT4の画面
MetaTrader 4 (MT4) のFileタブには、トレーディングプラットフォームの基本的なファイル操作と設定に関連するさまざまなオプションが含まれています。
Fileタブ
New Chart – 新しいチャートを開くためのオプションです。利用可能な通貨ペアや商品を選択して、新しいチャートウィンドウを開始します。
Open Offline – オフラインで保存されたチャートを開くためのオプションです。インターネット接続がない状態で、以前に保存したチャートを表示することができます。
Open Data Folder – MT4のデータフォルダを開くオプションです。エキスパートアドバイザー(EA)、インジケーター、スクリプトなどのファイルを含む、MT4のインストールデータにアクセスすることができます。
Login to Trade Account – トレードアカウントにログインするためのオプションです。アカウント番号とパスワードを使用して、既存のトレードアカウントにアクセスします。
Open an Account – 新しいトレーディングアカウントを開設するためのオプションです。デモアカウントやリアルアカウントの開設が可能です。
Save As Picture – 現在のチャートのスクリーンショットを保存するオプションです。チャートの画像を保存して、他の人と共有することができます。
Profiles – チャートのレイアウトや設定を保存・管理するためのオプションです。異なるチャートセットアップを簡単に切り替えることができます。
Print – 現在のチャートを印刷するためのオプションです。物理的なコピーが必要な場合に便利です。
Exit – MT4プラットフォームを閉じるためのオプションです。全ての作業を保存し、アプリケーションを終了します。
Viewタブ
Languages (言語): MT4の言語を変更します。
Toolbars (ツールバー): 標準、チャート、ラインスタディなど、さまざまなツールバーを表示または非表示にします。
Market Watch (マーケットウォッチ): 取引可能な通貨ペアや商品のリストを表示します。
Data Window (データウィンドウ): チャート上の任意のポイントの詳細な市場データを表示します。
Navigator (ナビゲーター): アカウント、インジケーター、エキスパートアドバイザー、スクリプトへの迅速なアクセスを提供します。
Terminal (ターミナル): 取引履歴、開いているポジション、アカウントの状況など、取引に関する情報を表示します。
Strategy Tester (ストラテジーテスター): エキスパートアドバイザーのバックテストと最適化を行います。
Fullscreen (全画面表示): MT4を全画面表示モードに切り替えます。
Insert タブ
“Insert” タブは、チャートにさまざまな分析ツールやオブジェクトを追加するために使用されます。技術指標、グラフィカルオブジェクト、さまざまな形の図形などが含まれています。
Indicators (指標)
MT4で提供される多数の技術指標をチャートに挿入できます。これらはトレンド指標、オシレーター、ボリューム指標など、さまざまなカテゴリーに分けられます。ユーザーは移動平均線、MACD、RSI、Bollinger Bandsなど、市場分析に広く使用される指標を選択してチャートに追加できます。
Lines (ライン)
トレーダーはトレンドライン、水平ライン、垂直ライン、フィボナッチリトレースメントなど、チャート分析に必要なラインを描画することができます。これらのラインは、サポートとレジスタンスのレベル、トレンドの方向性、価格の動きの可能性のある反転点を識別するのに役立ちます。
Channels (チャネル)
チャネルは市場のトレンドを捉えるために使用されます。トレーダーは標準的なチャネル、エクイディスタントチャネル、フィボナッチチャネルなど、異なるタイプのチャネルをチャートに挿入できます。
Gan Tools (ガンツール)
W.D. Gannの理論に基づくツールで、ガンライン、ガンファン、ガングリッドなどが含まれます。これらのツールは市場の時間と価格の関係を分析するのに使用されます。
Fibonacci Tools (フィボナッチツール)
フィボナッチリトレースメント、フィボナッチタイムゾーン、フィボナッチファン、フィボナッチアークスなど、フィボナッチ数列に基づくツールです。これらは市場の潜在的なサポートとレジスタンスレベルを検証するのに役立ちます。
Shapes (形状)
長方形、三角形、楕円など、チャートに追加できるさまざまな形状があります。これらは特定の価格帯やパターンを強調表示するために使用されます。
Arrows (矢印)
エントリーやエグジットポイントなど、チャート上の特定のイベントやレベルを指し示すために矢印を使用できます。
Text (テキスト)
チャート上に直接テキストを挿入して、注釈を加えることができます。これは特定の分析やメモを記録するのに便利です。
Chartsタブ
Chartsタブは、チャートの表示や管理に関する様々なオプションを提供します。このタブを通じて、ユーザーはチャートの見た目をカスタマイズし、分析に適した環境を整えることができます。以下に主な機能を説明します。Bar Chart (バーチャート)
このオプションを選択すると、チャートがバーチャート形式で表示されます。各バーは特定の時間枠内の価格の開始、終了、高値、低値を示します。
Candlesticks (ローソク足)
ローソク足チャートを選択すると、価格データがローソク足形式で表示されます。これはトレーダーにとって非常に人気のある表示方法で、価格の動きを視覚的に捉えやすくします。
Line Chart (線チャート)
線チャートを選択すると、選択した時間枠における終値を結んだ線で価格が表示されます。これは市場のトレンドを追うのに役立ちます。Foreground chart (最前面チャート)
このオプションを有効にすると、チャート上のすべての要素(インジケーター、ライン、テキストなど)が価格バーまたはローソク足の前面に表示されます。Chart Shift (チャートシフト)
チャートを右にシフトさせ、チャートの右側に空白のスペースを作り出します。これにより、現在の価格の近くで作業しやすくなります。Auto Scroll (オートスクロール)
このオプションが有効の場合、新しい価格が表示されるとチャートが自動的にスクロールし、常に最新の価格が表示されるようになります。Chart Indicators List (チャート指標リスト)
チャートに適用されているすべてのインジケーターのリストを表示します。ここからインジケーターの編集や削除が行えます。
Templates (テンプレート)
チャートの設定やインジケーターを保存し、別のチャートに簡単に適用できるテンプレートを管理します。これにより、好みのチャート設定を簡単に再利用できます。
Properties (プロパティ)
チャートの色や他の視覚的要素をカスタマイズするためのオプションを提供します。背景色、グリッド色、バーの色など、細かい部分の調整が可能です。
Tools タブ
Toolsタブは、取引の実行、履歴の閲覧、アカウントオプションの設定など、さまざまな機能へのアクセスを提供します。主な機能には以下が含まれます。
New Order (新規注文): 新しい取引注文を行うためのウィンドウを開きます。市場注文や指値注文など、さまざまな注文タイプを選択できます。
History Center (履歴センター): 過去の市場データや取引履歴を閲覧します。特定の通貨ペアの歴史的データを分析するのに便利です。
Global Variables (グローバル変数): エキスパートアドバイザー(EA)やスクリプトで使用されるグローバル変数を管理します。
Options (オプション): MT4の主要な設定をカスタマイズします。取引の実行設定、チャートの表示オプション、通知設定などを含みます。
MetaQuotes Language Editor (MQLエディター): エキスパートアドバイザー(EA)、カスタム指標、スクリプトを開発するための統合開発環境(IDE)を開きます。
Windowタブ
Windowタブは、チャートウィンドウの管理とナビゲーションを容易にするための機能を提供します。このタブは、複数のチャートウィンドウを効率的に整理し、特定のチャート間での移動をスムーズにするために特に便利です。
New Window (新しいウィンドウ)
新しいチャートウィンドウを開きます。特定の通貨ペアや取引商品のチャートを新たに表示する際に使用します。
Cascade (カスケード表示)
開いているすべてのチャートウィンドウを重ねて表示します。各ウィンドウが少しずつずれて表示されるため、複数のチャートを同時に確認できます。
Tile Horizontally (水平に並べて表示)
開いているチャートウィンドウを画面の幅に合わせて水平方向に並べて表示します。これにより、複数のチャートを一覧でき、各チャートを平等に比較するのに適しています。
Tile Vertically (垂直に並べて表示)
開いているチャートウィンドウを画面の高さに合わせて垂直方向に並べて表示します。これは、特に縦長のモニターで複数のチャートを見る際に役立ちます。
Arrange Icons (アイコンを整理)
最小化されたチャートウィンドウをタスクバー上で整理します。これにより、最小化されたチャート間でのナビゲーションが容易になります。
Windows… (ウィンドウ…)
開いているすべてのチャートウィンドウのリストを表示します。このリストから特定のチャートウィンドウを選択してアクティブにすることができます。
メタエディタ画面の見方
メタエディタ
メニューバー
Create New Document-スクリプト、インジケーター、またはエキスパートアドバイザーを記述するために使います。特定の機能を実装したい場合に便利です。
Create New Projec-より大規模で構造化された開発作業のために使用されます。このオプションを選択すると、複数のファイルやディレクトリを含むプロジェクト構造が作成されます。プロジェクトは、複数のモジュールを統合する大規模なアプリケーションを開発する際に特に役立ちます。
View MetaQuotes Language Library-現在作られているファイルやフォルダを参照できます。
insert clipboard contents-クリップボードに保存されている内容を現在編集中のドキュメントやファイルに挿入する機能です。クリップボードは、コンピュータ上で一時的にデータを保存するための領域です。
Go To Definition-変数、関数、クラスなどのシンボルの定義に直接ジャンプする際に便利です。コード内で宣言されている要素を迅速に見つけることができます。
compile-ユーザーが作成したMQL4言語で書かれたプログラム(エキスパートアドバイザー、カスタムインジケーター、スクリプトなど)をコンパイルするための機能を提供するインターフェイスの一部です。コンパイルとは、人間が読み書きできるプログラムコードを、コンピュータが実行可能な形式に変換するプロセスのことを指します。このタブを使用することで、ユーザーは自分のコードに誤りがないかを確認し、MT4プラットフォームで実行可能な形式に変換することができます。
StartResume debugging-プログラムのバグや問題を特定します。MT4のメタエディタでは、変数の値を監視したり、プログラムの挙動を詳細に調べたりすることができます。デバッグを通じて、コード内の論理エラーや実行時の例外など、コンパイル時には発見できなかった問題を特定し、修正することが可能です。
Difference of Versions-ファイルやドキュメントの異なるバージョン間の違いを比較し、表示するために使用されます。
Start On Profiling-プロファイリングは、コードの実行時間やメモリ使用量など、プログラムのパフォーマンスを分析するプロセスです。プロファイリングプロセスが完了すると、結果が表示され、どの関数が最も時間を要しているか、どのコード行が最適化のために注目すべきかがわかります。
style your source code-ソースコードを整形し、読みやすくするためのツールです。
下部のタブ
下部のタブには、開発プロセスをサポートするための様々なツールがあります。
Errors -コンパイルプロセス中に発見されたエラーや警告を表示します。MQL4言語でスクリプト、インジケーター、エキスパートアドバイザーを開発する際、コードに文法的な問題やその他の問題がある場合、それらはすべてこのタブにリストされます。エラーメッセージをクリックすると、該当するコードの行に直接ジャンプすることができ、問題の修正が容易になります。
Search -開発中のコード内で特定のテキストやコードを検索するために使用されます。大規模なプロジェクトや複数のファイルにわたる開発作業を行っている場合、この機能は特定の関数、変数名、またはその他のコード要素を迅速に見つけるのに役立ちます。
CodeBase -MT4コミュニティによって共有されたエキスパートアドバイザー、インジケーター、スクリプトなどのMQL4プログラムを提供しています。このリソースを利用することで、他のトレーダーや開発者が作成した既存のツールを利用して、自分のトレーディング戦略を拡張することができます。
Public Projects -オープンソースのプロジェクトや他の開発者が公開しているプロジェクトを探索するために使用されます。このタブを通じて、共同で作業したいプロジェクトに参加したり、自分のプロジェクトを公開してコミュニティのメンバーと共有したりすることが可能です。
Journal -メタエディタの使用中に発生したイベントのログが書かれます。コンパイル操作、デバッグセッションの詳細が含まれます。
MQL言語の基本的な構文とスクリプトの開発
スクリプトと実行方法
MT4のスクリプトとは、一度実行されると自動的に停止する小規模なプログラムです。開発中のロジックや関数をスクリプトに迅速に実装し、MT4のチャート上で直接実行することで、即座に結果を確認することが可能です。
スクリプトは、一度実行されると自動的に終了するため、繰り返し実行したい場合は、再度チャートにドラッグ&ドロップする必要があります。また、スクリプトは主に一回限りのタスクや簡単な操作に使用され、継続的な市場監視や自動取引にはエキスパートアドバイザーが使用されます。
メタエディタでスクリプトを実行する基本的な手順
- メタエディタを開く: MetaTraderプラットフォームを開いて、「ツール」メニューから「MetaQuotes Language Editor」を選択するか、プラットフォームの標準ツールバーにあるMetaEditorを開くアイコンをクリックします。
- 新しいスクリプトを作成する
- 新しいスクリプトを作成するには、メニューの「ファイル」→「新規」を選択し、「スクリプト」を選びます。必要な情報を入力し、「OK」をクリックします。
- 既存のスクリプトを開くには、「ナビゲータ」ウィンドウからスクリプトを探し、ダブルクリックするか、右クリックして「修正」を選びます。
- スクリプトを編集する: エディタでスクリプトのコードを編集します。
- スクリプトをコンパイルする: コードの編集が完了したら、ツールバーの「コンパイル」ボタンをクリックするか、F7キーを押してスクリプトをコンパイルします。エラーがなければ、使用可能です。
- スクリプトを実行する: MT4に戻ります。「ナビゲータ」ウィンドウで、実行したいスクリプトを見つけます。スクリプトをチャート上にドラッグ&ドロップするか、右クリックして「チャート上で実行」を選択します。結果は、ターミナルに画面下タブのExpertsタブに表示されます。
// これは私たちの最初のスクリプトです
void OnStart() // スクリプトのメイン関数
{
Print(“Hello, World!”); // コンソールにメッセージを出力
}
この関数は、スクリプトが開始されたときに一度だけ自動的に呼び出されます。
基本構文:変数、データ型、演算子
データ型と変数
データ型は、変数に格納できる値の種類を定義します。MQL4で一般的に使用されるデータ型には以下のものがあります:
int: 整数を格納。例: -100, 0, 100
double: 浮動小数点数を格納。例: -123.45, 0.0, 123.45
string: 文字列を格納。例: “Hello, World!”
bool: 真偽値(trueまたはfalse)を格納。
変数は、データを格納するための名前付きの「容器」です。変数を宣言するときは、データ型を指定する必要があります。
void OnStart()
{
int sum = 10 + 5; // 15
int difference = 10 – 5; // 5
double product = 10 * 0.5; // 5.0
double quotient = 10 / 4; // 2.5
bool isEqual = (sum == difference); // false
bool isNotEqual = (sum != difference); // true
Print(“合計: “, sum); // “合計: 15” と表示
Print(“差分: “, difference); // “差分: 5” と表示
Print(“積: “, product); // “積: 5.0” と表示
Print(“商: “, quotient); // “商: 2.5” と表示
Print(“等しいか: “, isEqual); // “等しいか: false” と表示
Print(“等しくないか: “, isNotEqual); // “等しくないか: true” と表示
}
制御構造:条件分岐
今回は、プログラムの流れを制御するための重要な概念である条件分岐に焦点を当てます。条件分岐を使用すると、特定の条件に基づいて異なるアクションを実行させることができます。
if文
if文は、単一の条件が真(true)の場合にコードブロックを実行します。
int price = 100;
if(price > 50) {
Print(“greater than 50”);
}
if-else文
if-else文は、条件が真(true)の場合と偽(false)の場合で異なるコードブロックを実行します。
int score = 75;
if(score >= 80) {
Print(“合格”);
} else {
Print(“不合格”);
}
if-else if-else文
複数の条件をチェックするには、if-else if-else文を使用します。
int temperature = 30;
if(temperature > 30) {
Print(“とても暑い”);
} else if(temperature > 20) {
Print(“暑い”);
} else {
Print(“快適”);
}
条件分岐は、プログラム内で異なるシナリオに基づいて異なるアクションを実行するために不可欠です。if文、if-else文、およびswitch文を使用することで、より複雑なロジックをプログラムに組み込むことができます。
制御構造:ループ:(for、while)
MQL4のループは、ある条件が満たされる間、同じコードブロックを繰り返し実行するために使用されます。ループにはforループとwhileループがあります。
forループ
forループは、繰り返し回数が明確な場合に便利です。初期化式、条件式、イテレーション式から構成されます。
for (初期化式; 条件式; イテレーション式) {
// 繰り返し実行されるコードブロック
}
初期化式
初期化式はループが開始する前に一度だけ実行される部分です。通常、ループで使用する変数の初期値を設定するために使われます。例えば、int i = 0;という式では、ループカウンタとして使われる変数iを0に初期化しています。
条件式
条件式はループの各繰り返し前に評価される式です。この条件がtrueである限り、ループの本体が実行され続けます。条件式がfalseと評価された場合、ループは終了します。例えば、i < 5;という条件では、iが5未満である間、ループは続けられます。
イテレーション式
イテレーション式はループの本体が実行された後で実行される式です。通常、これはループのカウンタの値を更新するために使われます。
例えば、i++という式は、iの値を1増加させます。
for(int i = 0; i < 5; i++) {
Print(“for loop repetition: “, i);
}
このforループは、iの値が0から始まり、5未満の間(つまり、0, 1, 2, 3, 4の各値に対して)繰り返され、各繰り返しでiの値を1ずつ増加させます。ループの各繰り返しで、Print関数が実行され、”for loop repetition: “に続いて現在のiの値が出力されます。
for loop repetition: 0
for loop repetition: 1
for loop repetition: 2
for loop repetition: 3
for loop repetition: 4
whileループ
whileループは、繰り返しを続ける条件が変更されるまでループを実行し続ける場合に使用します。
int i = 0;
while(i < 5) {
Print(“while loop repetition: “, i); i++;
}
この例では、iが5未満である間、ループ内のコードを実行します。ループの各繰り返し後にiをインクリメント(1増やす)することで、いずれ条件が偽になりループから抜けます。
while loop repetition: 0
while loop repetition: 1
while loop repetition: 2
while loop repetition: 3
while loop repetition: 4
練習問題:繰り返しを使った簡単な計算
練習として、1から10までの数字の合計を計算するプログラムを書いてみましょう。
//orループを使用する場合:
int sum = 0;
for(int i = 1; i <= 10; i++) {
sum += i;
}
Print(“sum from 1 to 10: “, sum);
//whileループを使用する場合:
int sum = 0;
int i = 1;
while(i <= 10) {
sum += i; i++;
}
Print(“sum from 1 to 10: “, sum);
forループとwhileループを使って、特定の条件下でコードブロックを繰り返し実行する方法を学びました。ループは、同じ操作を複数回実行する必要がある場合に非常に便利です。
関数:標準関数とカスタム関数の作成
標準関数:標準関数は、トレーディング戦略の開発やデータ分析に不可欠なツールです。
標準関数は、計算、チャート操作、取引注文など、さまざまなタスクを簡単に実行するために使われます。
標準関数は、MQL4にあらかじめ組み込まれている関数です。例えば、Print() 関数は最も一般的な標準関数の一つで、データをコンソールに出力します。
他にも、OrderSend()(注文を送信)、iMA()(移動平均を計算)、MathMax()(最大値を返す)など、様々な標準関数があります。
Print() 関数
Print() は、文字列や数値をコンソールに出力する基本的な標準関数です。
デバッグ時に変数の値を確認するために頻繁に使用されます。
double balance = AccountBalance();
Print(“Account balance: “, balance);
OrderSend() 関数
OrderSend() は、市場注文や指値注文を送信するための関数です。
ロットサイズ、注文のタイプ、価格、スリッページ、ストップロス、テイクプロフィットなど、注文に関連するパラメータを指定できます。
//+——————————————————————+
//| test.mq4 |
//| Copyright 2024, MetaQuotes Ltd. |
//| https://www.mql4.com |
//+——————————————————————+
#property copyright “Copyright 2024, MetaQuotes Ltd.”
#property link “https://www.mql4.com”
#property version “1.00”
#property strict// MAGIC_NUMBER の宣言と割り当て
int MAGIC_NUMBER = 123456; // 例として123456を使用//+——————————————————————+
void OnStart() // スクリプトのメイン関数
{
int ticket = OrderSend(Symbol(), OP_BUY, 1.0, Ask, 3, 0, 0, “order comment”, MAGIC_NUMBER, 0, clrNONE);
if(ticket < 0) {
Print(“order error: “, GetLastError());
}
}
コードの解説
int ticket: 注文が正常に送信された場合、この変数は注文のチケット番号(一意の識別子)を格納します。注文送信が失敗した場合、-1 が返されます。
OrderSend: これは、新しい注文をブローカーに送信するための関数です。
Symbol(): 現在選択されている通貨ペアまたは取引商品のシンボルを返します。
OP_BUY: 注文タイプを指定します。この場合、OP_BUY は買い注文を意味します。
1.0: 注文の量を指定します。この場合、1ロットの買い注文です。
Ask: 買い注文の価格。Ask は現在の買い価格を表します。
3: スプレッド(買い価格と売り価格の差)を考慮して、注文を許容する最大スリッページ(価格のずれ)を指します。この例では、3ポイントです。
0, 0: ストップロス(損切り価格)とテイクプロフィット(利益確定価格)を指定します。0 は、これらの価格が設定されていないことを意味します。
“注文コメント”: 注文に関連するコメントです。このコメントは取引履歴で確認できます。
MAGIC_NUMBER: 注文を識別するためのユニークな番号。これにより、スクリプトやエキスパートアドバイザーが自分の注文を他の注文と区別できます。
0: 注文の有効期限。0 は注文に有効期限がないことを意味します。
clrNONE: 注文の色を指定します。clrNONE は色を指定しないことを意味します。
エラーチェック部分:
if(ticket < 0) { Print(“注文エラー: “, GetLastError()); }
この部分は、注文が失敗した場合(ticket が -1 の場合)にエラーメッセージをログに出力します。GetLastError() 関数は、最後に発生したエラーのコードを返します。このコードを使用して、注文失敗の原因を特定できます。
このコードスニペット全体は、MT4 プラットフォーム上で新しい買い注文を出し、その成否をチェックするためのものです。正常に注文が出されると、その注文のチケット番号が ticket 変数に格納されます
iMA() 関数
iMA() 関数は、指定された期間と価格データに基づいて移動平均を計算します。
移動平均の種類(単純、指数、平滑、線形加重)、期間、シフト、価格タイプを指定できます。
double iMA(シンボル ,時間枠, 移動平均の期間,MAのシフト , MAの種類 , 適用される価格バーのシフト);
MAのシフト (shift): 移動平均線をチャート上で左右にシフト(移動)させるバーの数。正の値は未来に向かってシフトし、負の値は過去に向かってシフトします。通常は0が使用され、これはシフトなしを意味します。
MAの種類 (ma_type): 移動平均のタイプ。例えば、MODE_SMA(単純移動平均)、MODE_EMA(指数移動平均)、MODE_SMMA(平滑化移動平均)、MODE_LWMA(線形加重移動平均)などがあります。適用される価格バーのシフト (applied_price): 移動平均の計算に使用する価格の種類。例えば、PRICE_CLOSE(終値)、PRICE_OPEN(始値)、PRICE_HIGH(高値)、PRICE_LOW(安値)などがあります。
//+——————————————————————+
//| test.mq4 |
//| Copyright 2024, MetaQuotes Ltd. |
//| https://www.mql4.com |
//+——————————————————————+
#property copyright “Copyright 2024, MetaQuotes Ltd.”
#property link “https://www.mql4.com”
#property version “1.00”
#property strict
int MAGIC_NUMBER = 123456;
void OnStart()
{
double ma = iMA(Symbol(), PERIOD_D1, 14, 0, MODE_SMA, PRICE_CLOSE, 0);
Print(“Daily 14-period simple moving average: “, ma);
}
コードの解説
double ma:
double は変数の型で、浮動小数点数を表します。
ma はこの変数の名前で、この場合は計算された移動平均の値を格納するために使用されます。
iMA:
iMA は、移動平均(Moving Average)を計算するための組み込み関数です。
Symbol():
Symbol() 関数は、現在選択されている通貨ペアまたはトレードシンボルの名前を返します。
PERIOD_D1:
これは、使用する時間枠を指定します。PERIOD_D1 は1日足を意味します。
14:
これは移動平均の期間を指定します。ここでは14を使用しているため、14日間の平均を計算します。
0:
これは移動平均のシフトを指定します。0を指定すると、現在のバーに対するシフトはありません。
MODE_SMA:
これは移動平均のタイプを指定します。MODE_SMA は単純移動平均(Simple Moving Average)を意味します。
PRICE_CLOSE:
これは、移動平均を計算するために使用する価格タイプを指定します。PRICE_CLOSE は各バーの終値を使用することを意味します。
0 (最後のパラメータ):
これは計算された移動平均をどのバーに対して適用するかを指定します。0は現在のバーを指し、1は1バー前を指します。
コード全体として、現在のシンボルに対する1日足の単純移動平均を、14日間の期間で、現在のバーに適用して計算し、その結果を変数 ma に格納しています。
MathMax() 関数
MathMax() は、二つの数値のうち大きい方を返す関数です。
最大値の決定、価格データの解析、他の計算での利用などに使用されます。
double highestPrice = MathMax(High[0], High[1]);
Print(“highest price: “, highestPrice);
High[]は、MQL4で定義されている組み込みの配列で、チャート上の各バーの最高価格を保持します。High[0]は最新バー(現在のバー)の最高価格を、High[1]は直前のバーの最高価格を指します。
例えば市場の短期的な最高価格を追跡したい場合や、特定のトレーディング戦略で直近の価格のピークを分析したい場合に役立ちます。
OrderClose()関数
OrderClose()関数は、MQL4において開かれているトレードポジションを閉じるために使用されます。この関数を使用するには、閉じたいポジションのオーダー番号、クローズしたいロット数、クローズ時の価格、そしてスリッページ(許容される価格滑り量)を指定する必要があります。
OrdersTotal()は、アカウントに現在オープンされているトレードオーダーの総数を返します。この数値には、市場注文と保留注文の両方が含まれます。
OrdersTotal()関数
OrdersTotal()は特に、エキスパートアドバイザー(EA)やカスタムインディケータ、スクリプトなどを開発する際に、オープンオーダーを管理するためによく使用されます。
bool OrderSelect(
int ticket, // オーダー番号、またはオーダーインデックス
int select, // 選択モード
int pool=MODE_TRADES // オーダープール(省略可能)
);
コードの解説
ticket:選択するオーダーのチケット番号、またはオーダーリストのインデックスです。選択モードによって、このパラメーターがチケット番号として解釈されるか、またはオーダーリスト内のインデックスとして解釈されるかが決まります。
select:オーダーの選択モードを指定します。SELECT_BY_TICKETはticketパラメーターをオーダーのチケット番号として解釈し、SELECT_BY_POSはオーダーリスト内のインデックスとして解釈します。
pool:オーダープールを指定します。MODE_TRADESは現在のオープンポジションと保留オーダーを対象にし、MODE_HISTORYはクローズされたポジションとキャンセルされた保留オーダーを対象にします。デフォルトはMODE_TRADESです。
OrderSelect()もMetaTrader 4 (MT4) で使用されるMQL4言語の標準関数の一つです。この関数は、特定のトレードオーダーを選択し、そのオーダーに関連する操作を行うために使用されます。選択されたオーダーに対しては、その詳細を取得したり、オーダーを閉じたり、変更したりすることができます。
OrderTicket()はMetaTrader 4 (MT4) および MetaTrader 5 (MT5) において使用されるMQL4およびMQL5言語の標準関数です。この関数は、現在選択されているトレードオーダーの一意なチケット番号を返します。チケット番号は、トレードオーダーを特定し、管理するために使用される、そのオーダー固有の識別子です。
OrderTicket()関数は、他のオーダー関連関数と同様に、まずOrderSelect()関数を使用して特定のオーダーを選択した後に呼び出されます。この関数はパラメータを取らず、選択されたオーダーのチケット番号を整数値として返します。
//1番古いのオーダーをクローズする
void OnStart()
{
// オープンされているオーダーがあるか確認
if (OrdersTotal() > 0) {
// 最初のオーダーを選択
if (OrderSelect(0, SELECT_BY_POS)) {
int ticket = OrderTicket();
double lots = OrderLots();
double price;
int slippage = 3;// オーダータイプに応じて適切なクローズ価格を設定
if (OrderType() == OP_BUY) {
// 買いポジションの場合、Ask価格を使用
price = MarketInfo(OrderSymbol(), MODE_ASK);
} else if (OrderType() == OP_SELL) {
// 売りポジションの場合、Bid価格を使用
price = MarketInfo(OrderSymbol(), MODE_BID);
}// オーダーをクローズ
bool result = OrderClose(ticket, lots, price, slippage, clrNONE);
if (result) {
Print(“Order “, ticket, ” is closed.”);
} else {
Print(“Close error: Error “, GetLastError());
}
}
} else {
Print(“No open orders.”);
}
}
iOpen()関数
iOpen()関数は、MQL4で特定のシンボルとチャートの時間枠における、指定されたバーのオープン価格を取得するために使用されます。この関数は、テクニカル分析やトレーディング戦略の開発において非常に重要で、市場の動向を把握するための基本的なデータの一つを提供します。
double iOpen(
シンボル名 , 時間枠 , 何番目のバーか(0は現在のバー)
);
EURUSDの1時間足チャートにおける最新バー(現在のバー)のオープン価格を取得する例は以下の通りです:
double currentOpenPrice = iOpen(“EURUSD”, PERIOD_H1, 0);
Print(“Current bar opening price: “, currentOpenPrice);
この関数を使用することで、指定したシンボルと時間枠の任意の過去バーのオープン価格を簡単に取得でき、それをもとにした分析や判断が可能になります。たとえば、特定の時間枠での価格動向を分析したり、オープン価格を基にしたエントリーやエグジット戦略を立てる際に有用です。
指定された条件に該当するバーが存在しない場合i()関数は0.0を返します。
iClose()関数
MQL4(MetaQuotes Language 4)で使用される関数の一つで、特定のシンボルの特定の時間枠における指定されたバーのクローズ価格を取得するために使用されます。
double iClose(シンボル名,時間枠,何番目のバーか(0は現在のバー));
double lastClosePrice = iClose(“EURUSD”, PERIOD_H1, 0);
Print(“lastClosePrice: “, lastClosePrice);
このコードは、EURUSDの1時間足チャートにおける最新バーのクローズ価格を取得し、それを出力します。iClose()関数を使用することで、過去の任意のバーのクローズ価格を取得し、それに基づいて市場分析を行ったり、取引戦略を調整したりすることができます。例えば、特定の時間枠における価格のトレンドを分析するために過去数バーのクローズ価格を比較したり、移動平均などの指標を計算する際の基礎データとして使用することが可能です。
指定された条件に該当するバーが存在しない場合iClose()関数は0.0を返します。
iHigh()関数
iHigh()関数は、特定のシンボルと時間枠における指定されたバーの最高価格(High価格)を取得するために使用されます。
double iHigh(シンボル名,時間枠,何番目のバーか(0は現在のバー));
例:EURUSDの1時間足の最新バーの最高価格を取得する例
double highPrice = iHigh(“EURUSD”, PERIOD_H1, 0);
Print(“Best price for latest bar: “, highPrice);
このコードは、EURUSDの1時間足チャートにおける最新バーの最高価格を取得し、それを出力します。iHigh()関数を使用することで、過去の任意のバーの最高価格を取得し、それに基づいて市場分析を行ったり、取引戦略を調整したりすることができます。例えば、特定の時間枠における価格の抵抗レベルを分析するために過去数バーの最高価格を比較したり、ブレイクアウト戦略を立てる際に重要な情報として使用することが可能です。
iHigh()関数は、特に市場の上昇トレンドや価格の抵抗点を特定する際に役立つ重要な関数です。正確な市場分析や効果的な取引戦略のために、他の関数(iLow()、iOpen()、iClose()など)と組み合わせて使用されることが一般的です。
iLow()関数
iLow()関数は、MQL4で特定のシンボルと時間枠において、指定されたバーの最低価格(Low価格)を取得するために使用される関数です。この関数は、市場の価格動向を分析し、テクニカル指標の計算、トレーディング戦略の開発、または市場のサポートレベルを特定する際に重要な役割を果たします。
iLow()関数の構文
double iLow( シンボル名, 時間枠,何番目のバーか(0は現在のバー) );
例:
EURUSDの1時間足の最新バーの最低価格を取得する
double lowPrice = iLow(“EURUSD”, PERIOD_H1, 0);
Print(“Latest bar lowest price: “, lowPrice);
このコードは、EURUSDの1時間足チャートにおける最新バーの最低価格を取得し、それを出力します。iLow()関数を使用することで、過去の任意のバーの最低価格を簡単に取得し、それに基づいて市場のサポートレベルを分析したり、取引戦略を調整したりすることができます。例えば、特定の時間枠における価格のサポートレベルを特定するために、過去数バーの最低価格を比較することがあります。
iLow()関数は、市場の下降トレンドやサポートポイントを特定する際に特に有用です。効果的な市場分析や取引戦略のために、iHigh()、iOpen()、iClose()といった他の関数と組み合わせて使用されることが一般的です。
カスタム関数の作成
MetaTrader 4 (MT4) でのカスタム関数の作成は、MQL4(MetaQuotes Language 4)を使用して行います。カスタム関数は、特定の処理を実行するコードのセクションで、プログラム全体で再利用可能です。これにより、コードの読みやすさが向上し、メンテナンスが容易になります。カスタム関数はエキスパートアドバイザー、カスタムインディケータ、スクリプトなど、さまざまな場面で使用できます。
カスタム関数の基本的な構造
タイプ 関数名(パラメータ1のタイプ パラメータ1, パラメータ2のタイプ パラメータ2, …)
{
// 処理
return 値; // タイプに応じた値を返す
}
タイプ: 関数が返す値のデータ型です。voidを指定すると、関数は値を返しません。
関数名: 関数を識別するための名前です。
パラメータ: 関数に渡すことができる変数です。これらはオプションで、必要に応じて複数指定することができます。
処理: 関数内で実行するコードです。
return: 関数が結果として値を返す場合、このキーワードを使用します。
カスタム関数の例
二つの数値を受け取り、その合計を返す簡単なカスタム関数の例です:
// 二つの数値の合計を返す関数
double AddNumbers(double number1, double number2)
{
double sum = number1 + number2; // 合計を計算
return sum; // 合計を返す
}
この関数を使用するには、関数名AddNumbersに続けて、括弧内に引数(この場合は二つの数値)を指定して呼び出します:
void OnStart()
{
double result = AddNumbers(5, 10); // 関数を呼び出し、結果を変数に保存
Print(“total: “, result); // 結果を表示
}
この例では、AddNumbers関数を定義してから、OnStart関数内でそれを呼び出しています。AddNumbers関数は、二つの数値の合計を計算し、その結果を返します。
カスタム関数を作成することで、コードが整理がされ、プログラムの管理がしやすくなります。
インディケーター
インディケーターの種類
MetaTrader 4 (MT4)には、多くの標準インディケーターが組み込まれており、これらは一般的にトレンド、オシレーター、ボリューム、およびカスタムインディケーターのカテゴリに分けられます。
トレンドインディケーター
トレンドインディケーターは市場のトレンドの方向と強度を特定するのに役立ちます。
移動平均 (MA): 市場の平均価格を一定期間にわたって計算し、トレンドを平滑化します。
Bollinger Bands (BB): 移動平均の周囲に配置された2つの標準偏差バンドで、市場のボラティリティを測定します。
移動平均収束拡散 (MACD): 2つの移動平均の差を計算し、トレンドの勢いと方向を示します。
パラボリックSAR: トレンドの方向と転換点を示すために、価格チャート上に点を配置します。
オシレーター
オシレーターは市場が過買または過売の状態にあるかどうかを特定するのに役立ちます。
相対力指数 (RSI): 価格変動の勢いを測定し、過買や過売の条件を識別します。
ストキャスティクス: 価格の範囲内での終値の位置を分析し、市場の勢いを測定します。
Commodity Channel Index (CCI): 価格がその平均からどの程度離れているかを示し、新しいトレンドの開始を特定します。
ボリュームインディケーター
ボリュームインディケーターは取引量に関連する情報を提供し、市場の強さを判断します。
ボリューム: 取引量の変化を示し、トレンドの強さを評価します。
On-Balance Volume (OBV): ボリュームを使用して価格の動きを確認し、トレンドの確認または逆転を識別します。
カスタムインディケーターの作成手順
単純な移動平均(SMA)ベースのインディケーター
特定の期間の価格データに基づいて平均値を描画します。
バッファとは、データを入れておく箱です。インディケーターが市場データを解析し計算を行った結果は、これらのバッファに格納され、チャート上に描画されます。
「MA」は「Moving Average」の略で、移動平均を意味します。
//+——————————————————————+
//| MyIndi1.mq4 |
//| Copyright 2024, MetaQuotes Ltd. |
//| https://www.mql4.com |
//+——————————————————————+
#property copyright “Copyright 2024, MetaQuotes Ltd.”
#property link “https://www.mql4.com”
#property version “1.00”
#property strict
#property indicator_chart_window
// インディケータのバッファを宣言
double maBuffer[];
// ユーザー入力パラメータ
extern int maPeriod = 14; // 移動平均の期間
//+——————————————————————+
//| Custom indicator initialization function |
//+——————————————————————+
int OnInit()
{
// インディケーターのバッファを設定
SetIndexBuffer(0, maBuffer);
SetIndexStyle(0, DRAW_LINE);
// インディケーターの名前とラベルを設定
IndicatorShortName(“Custom SMA (” + IntegerToString(maPeriod) + “)”);
SetIndexLabel(0, “SMA(” + IntegerToString(maPeriod) + “)”);
ArraySetAsSeries(maBuffer, true);
return(INIT_SUCCEEDED);
}
//+——————————————————————+
//| Custom indicator calculation 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 < maPeriod)
return(0);
// バッファの計算
for(int i = 0; i < rates_total && !IsStopped(); i++)
{
if(i < maPeriod – 1)
{
maBuffer[i] = 0;
continue;
}
double sum = 0;
for(int j = 0; j < maPeriod; j++)
{
sum += close[i – j];
}
maBuffer[i] = sum / maPeriod;
}
return(0);
}
//+—————————————————————————————————+
買いまたは売りの矢印をチャート上に表示するインディケータ
移動平均のクロスオーバーを利用してトレンドの変化を検出し、それに応じて矢印を表示する MysecondIndicator
//+——————————————————————+
//| MysecondIndicator.mq4 |
//| Copyright 2024, MetaQuotes Ltd. |
//| https://www.mql4.com |
//+——————————————————————+
#property copyright “Copyright 2024, MetaQuotes Ltd.”
#property link “https://www.mql4.com”
#property version “1.00”
#property strict
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Blue
#property indicator_color2 Red
double buyArrowBuffer[];
double sellArrowBuffer[];
int MA_Period_Fast=9;
int MA_Period_Slow=21;
//+——————————————————————+
//| Custom indicator initialization function |
//+——————————————————————+
int OnInit()
{
SetIndexBuffer(0,buyArrowBuffer);
SetIndexBuffer(1,sellArrowBuffer);
SetIndexArrow(0,233);
SetIndexArrow(1,234);
ArraySetAsSeries(buyArrowBuffer,true);
ArraySetAsSeries(sellArrowBuffer,true);
IndicatorShortName(“Trend Arrows”);
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<MA_Period_Slow+1){
return(0);
}
int start=prev_calculated>1?prev_calculated-1:0;
for(int barIndex=start;barIndex<rates_total;barIndex++){
buyArrowBuffer[barIndex]=EMPTY_VALUE;
sellArrowBuffer[barIndex]=EMPTY_VALUE;
}
for(int currentBar=start+1;currentBar<rates_total;currentBar++){
double fastMA=iMA(NULL,0,MA_Period_Fast,0,MODE_SMA,PRICE_CLOSE,currentBar);
double slowMA=iMA(NULL,0,MA_Period_Slow,0,MODE_SMA,PRICE_CLOSE,currentBar);
double fastMAPrevious=iMA(NULL,0,MA_Period_Fast,0,MODE_SMA,PRICE_CLOSE,currentBar-1);
double slowMAPrevious=iMA(NULL,0,MA_Period_Slow,0,MODE_SMA,PRICE_CLOSE,currentBar-1);
if(fastMA>slowMA&&fastMAPrevious<=slowMAPrevious){
buyArrowBuffer[currentBar]=low[currentBar]-4*Point;
}else if(fastMA<slowMA&&fastMAPrevious>=slowMAPrevious){
sellArrowBuffer[currentBar]=high[currentBar]+4*Point;
}
}
return(rates_total);
}
//+—————————————————————————————————+
EAを開発するにあたって、ロジックの考え方
ロジックとは、取引戦略のルールや条件のことです。
EAのロジックには、次のようなものがあります。
エントリー条件:取引を開始するための条件。例えば、特定のテクニカル指標のシグナルや価格パターンなど。
エグジット条件:取引からの退出条件。利益を確定するための条件や、損失を限定するためのストップロスのレベルなど。
マネージメントルール:取引のリスクを管理するためのルール。例えば、1回の取引でリスクを取る資金の割合や、同時に開けるポジションの最大数など。
マネーマネジメント:資金管理戦略。取引のサイズやレバレッジの使用方法を決定します。
これらの条件やルールをコードに落とし込み、市場の状況に応じて自動的に取引を行うようにします。
ただし、市場の変動性や経済ニュースによって、EAのパフォーマンスは大きく変動することがありますので、定期的な調整が必要です。
ロジックとはどのように考えればいいのかといったことと、有名なEAでよく使用されているロジックについて紹介したいと思います。
まず、ロジックを考える上でやっていけないことを紹介したいと思います。
みなさんはこういう風な考え方をしたことはないでしょうか。
1つ目。
なんとなくロジックを決める。
例えばRSIとBBを組み合わせてみようかな、ゴールデンクロスとエンベロープなんか良さそうだなといった考え方ですね。
2つ目としてマンチカンの検証で満足するといったことはないでしょうか。
例えば5戦中5勝したから聖杯だなといったように決めつけるといったことですね。
3つ目として視野が狭いということが挙げられます。
例えば、EAの最適化を行う際に、BBの偏差を1.0から3.0まであまり考えもなしに0.1ずつ変えてみようといったことですね。
やってはいけない思考
これらの考え方はよく起こりうることだと思うのですけれども、ロジックを考える上ではあまり生産的ではありません。
そのため、まずはこれらの考え方を止めるところから意識してみましょう。
いよいよロジックの考え方についてなんですけども、ロジックを考える上で重要なことは2つあります。
1つ目は規則性を見つける、2つ目は幅広く検証をするということです。
規則性を見つける
ではまず1つ目の規則性を見つけるについて説明していきたいと思います。
世の中にはランダムウォーク理論という理論が存在します。
この理論は、値動きは完全ランダムで予測することができないとする理論なんですね。
この理論が正しいとすると、勝率は50%に必ず収束するため、FXではスプレットがある分必ず負けてしまうことになります。
こちらのランダムウォーク理論はテクニカル分析を全否定する理論になっています。
多くのトレーダーや分析家はランダムウォーク理論に異を唱えます。私も正しいとは思いません。
確かに相場がランダムな場合は予測しようがないので勝てません。
逆に考えると、ランダムでない部分を探して規則性を見つけることができれば、その規則性を利用して優位なトレードを行うことができます。
規則性を見つける
相場にはすでに規則性があるランダムではない要素がいくつかありますので、紹介したいと思います。
ランダムではない要素1つ目は出来高(ティック数)ですね。
こちらのヒストグラムは、ロウソク足のティック数、出来高を表示しています。
ティック数というのは、そのロウソク足で何回相場が動いたか、何回終値が更新されたかという数ですね。
こちらが見てもらうとわかると思うのですけども、このように山谷、山谷とジグザグになっていることがわかります。
どういうことかというと、出来高は時間帯によって大きく変わるということですね。
こちらヒストグラムで、特に出来高が少なくなっている部分は日本時間の早朝に当たるところです。
出来高が小さいというのはどういうことかというと、チャートが更新される数が少ないため、相場が緩やかになり、トレンドができにくいという特徴があります。
そのため、日本時間早朝は相場が緩やかなレンジ相場を利用した逆張りが有効と言われています。
こちらが俗に言う朝スキャというやつですね。
これがランダムではない例の一つとなります。
ランダムではない要素2つ目としては通貨ペアの相関関係ですね。
こちら3つのチャートは左からUSDJPY、EURJPY、GBPJPYです。
規則性がある通貨ペア
JPYとクロス円の通貨ペアを3つ持ってきました。
見てもらうとわかると思うのですけれども、異なる通貨ペアにもかかわらず、相場の動き方がとても似ていると思います。
他の通貨ペアと相関があるということは、チャートの値動きはランダムではないということになりますよね。
もしもチャートの値動きが完全にランダムだった場合、これらの通貨ペアは相関関係はないはずです。
例えば、この相関関係を利用して、クロス円の通貨ペアの中でUSD/JPY以外の通貨ペアが下降している場合、USD/JPYもこの後下降するんじゃないかといった予測を立てることができるんですね。
幅広く検証する
ロジックの考え方の重要な要素2つ目は幅広く検証するということです。
例えば、以下のようなEAがあったとしましょう。
通貨ペアはUSD/JPYは時間軸は5分足で、エントリーの条件として期間14偏差2.0のBBを価格が下抜けたときにエントリーする
売りエントリーではその逆で価格が上抜けたときというEAがあったとします。
こちらのEAバックテストで精度の低い結果となってしまいました。
このとき、EAを改善するためにはどのようなことをすればいいでしょうか。
幅広く検証する
まずダメな例として多くの方はやりがちだと思うのですけども、まずBBの時間を4から64、検査を1.0~3.0で変更しながら最適化を行うという方法ですね。
ダメなわけではないんですけども、現在のロジックの期間や偏差を少しずつ変えたところで改善されない可能性が高いです。
稀に偏差が1.0と1.1で全然違う、この0.1の差がポイントなんだといったようなことを言う方がいますが、あまり意味がありません。
たまたまその相場でうまくいくだけで、偏差0.1の差はあまり意味がないことが多いんですね。
なのでいきなり細かくパラメーターを変更しながら最適化を行うことはあまりよくありません。
ではどうすればいいかというと、幅広く検証するということですね。
具体的には、大きな要素から小さな要素に向けて検証や最適化を行っていくということです。
まず1つ目としては、別の通貨ペアや時間軸を試すということです。
値動きの特徴は通貨ペアや時間足によって異なるため、現代のロジックがより合う通貨ペアや時間足がある可能性があります。
もちろん、特定の通貨ペアは時間足を狙ったEAの場合は変更する必要はありませんが、まずは別の通貨ペアや時間足を試すと優位な結果になることが多いです。
2つ目としては、別の指標やロジックを追加するということですね。
現状BBだけだとして、RSIやATRなどの指標を追加してみるといったことがとても有効です。
また、ロジック以外でも、保有ポジション数を変えてみる、トレーリングストップを追加してみるといったことも挙げられます。
また、特に有効なのが、ロジックについても最適化でオンオフを行うということです。
例えば、BB、RSI、ATRという3つのロジックがあった場合、最適化でそれぞれのロジックをオンオフにしたときの結果を検証してみるといったことがとても有効です。
これらの検証を行った後に、最後にパラメーターの最適化を行いましょう。
このサイクルを行うことで、より良いEAを作成することができるようになります。
初めは難しいかもしれませんが、大きな要素から小さな要素に向けて幅広く検証するということを心がけてください。
エキスパートアドバイザー(EA)の開発とバックテスト
エキスパートアドバイザーの最低限必要な構造
//+——————————————————————+
//| FileName.mq4|
//| Copyright 2023, MetaQuotes Software Corp. |
//| http://www.metaquotes.net/ |
//+——————————————————————+
// EAのプロパティの定義
#property copyright “Copyright 2023, Your Name”
#property link “http://www.yourwebsite.com”
#property version “1.00”
#property strict
// 外部変数(ユーザーが入力ウィンドウで設定可能なパラメータ)
extern int tradingParameter = 10;
// エキスパートアドバイザーの初期化時に一度だけ実行される関数
int OnInit()
{
// 初期化コード
Print(“EAが初期化されました。”);
return(INIT_SUCCEEDED);
}
// 新しいティックごとに実行されるメイン関数
void OnTick()
{
// トレーディングロジック
Print(“新しいティックを受信しました。”);
}
// エキスパートアドバイザーの終了時に一度だけ実行される関数
void OnDeinit(const int reason)
{
// 終了コード
Print(“EAが終了します。”);
}
エキスパートアドバイザーを機能させるためには、少なくとも以下の関数を実装する必要があります:
#property命令
EAのメタ情報(著作権、リンク、バージョン)を設定します。
#property copyright “Copyright 2021, Your Company”
#property link “http://www.company.com”
#property version “1.0”
input(またはextern)
EAの設定パラメータで、ユーザーが入力ウィンドウから調整できるようにします。
input double LotSize = 0.1;
input int StopLoss = 50;
input int TakeProfit = 100;
OnInit()
EAが初期化されるときに一度だけ呼び出されます。
OnInit()は、EAやインディケーターがチャートに追加されたときに、必要な初期設定やリソースの確保を行います。
この関数内で、パラメータの初期化、外部リソースの読み込み、エラーチェックなどが行われます。OnInit()関数は通常、int型の値を返します。これにより、初期化の成功または失敗をMT4プラットフォームに通知します。
OnDeinit()
EAがチャートから削除されるときに呼び出されます。
OnDeinit()は、エキスパートアドバイザー(EA)やカスタムインディケーターがチャートから削除される際に呼び出される関数です。
OnDeinit()関数は、EAやインディケーターが停止する際にリソースを解放したり、必要なクリーンアップ作業を行うために使用されます。
例えば、開いているファイルのクローズ、動的に割り当てられたメモリの解放、オブジェクトの削除などが含まれます。
OnDeinit()関数は引数としてint reasonを受け取り、削除の理由を示します。
この関数は通常、void型を返しますが、特に返り値を使うことはありません。
void OnDeinit(const int reason) { // ここに終了時の処理を記述
Print(“EAがチャートから削除されました。”); }
OnDeinit() の使用例
チャート上に描画されたオブジェクトの削除です。
void OnDeinit(const int reason) { // カスタムインディケーターを削除
ObjectsDeleteAll(); // ファイルクローズやメモリ解放などのクリーンアップ CloseFile(); FreeMemory(); }
OnDeinit()関数は、EAやインディケーターのライフサイクルの終わりに非常に重要な役割を果たします。適切なクリーンアップとリソースの解放を行うことで、プログラムの安定性とメモリ効率を保つことができます。
OnTick()
新しい市場のティック(最小の価格変動)があるたびに呼び出されます。
OnTick()は、エキスパートアドバイザー(EA)の最も重要な部分であり、新しい市場のティック(最小の価格変動)があるたびに呼び出される関数です。
OnTick()関数は、市場データが更新されたとき、つまり新しい価格情報が入手可能になったときに呼び出されます。
この関数は、EAにとっての「心臓部」であり、取引判断や分析、注文実行などのトレーディングロジックがここに配置されます。
OnTick()は通常、返り値を持たず、特定の引数も取りません。
void OnTick() { // 新しいティックデータに基づいたロジックをここに記述 }
例えば、単純な移動平均交差戦略を実装する場合、OnTick()内で移動平均の計算と交差チェックを行います。
void OnTick() { // 現在の価格を取得
double currentPrice = Ask; // 移動平均を計算
double maFast = iMA(Symbol(), PERIOD_M15, 10, 0, MODE_SMA, PRICE_CLOSE); double maSlow = iMA(Symbol(), PERIOD_M15, 20, 0, MODE_SMA, PRICE_CLOSE);
// 移動平均の交差をチェック
if(maFast > maSlow && previousMaFast <= previousMaSlow) { // ここで買い注文のロジックを実行 } else if(maFast < maSlow && previousMaFast >= previousMaSlow) { // ここで売り注文のロジックを実行 } // 前回の移動平均の値を更新
previousMaFast = maFast; previousMaSlow = maSlow; }
OnTick()関数は、EAのトレーディングロジックを実行するための中心的な場所です。市場データの変化に応じて取引判断を行い、適切なタイミングで注文を出すためには、この関数内で正確なロジックを実装することが重要です。
実装例1カスタムインディケータの矢印チャートを元にトレードする
カスタムインディケーターからのシグナルは iCustom 関数を用いて取得します。
//+——————————————————————+
//| MyEa1.mq4 |
//| Copyright 2024, Your Name |
//| http://www.example.com |
//+——————————————————————+
#property copyright “Copyright 2024, Your Name”
#property link “http://www.example.com”
#property version “1.00”
#property strict
// カスタムインディケーターの名前
string indicatorName = “MysecondIndicator”;
// インディケーターのバッファインデックス
int buySignalIndex = 0;
int sellSignalIndex = 1;
//+——————————————————————+
//| Expert initialization function |
//+——————————————————————+
int OnInit()
{
// ここには特に初期化する必要があるものを配置
return(INIT_SUCCEEDED);
}
//+——————————————————————+
//| Expert deinitialization function |
//+——————————————————————+
void OnDeinit(const int reason)
{
// クリーンアップが必要な場合はここで行いますが、IndicatorAttach/Releaseは不要
}
//+——————————————————————+
//| Expert tick function |
//+——————————————————————+
void OnTick()
{
// 最新のバーのインデックスを取得
int rates_total = iBars(NULL, 0);
int shift = rates_total – 1;
// カスタムインディケーターからシグナルを取得
double buySignal = iCustom(NULL, 0, indicatorName, buySignalIndex, shift);
double sellSignal = iCustom(NULL, 0, indicatorName, sellSignalIndex, shift);
// 買いシグナルがある場合
if(buySignal != EMPTY_VALUE && OrdersTotal() == 0)
{
// 買い注文を出す
OrderSend(Symbol(), OP_BUY, 0.1, Ask, 2, 0, 0, “Buy Order”, 0, 0, clrGreen);
}
// 売りシグナルがある場合
if(sellSignal != EMPTY_VALUE && OrdersTotal() == 0)
{
// 売り注文を出す
OrderSend(Symbol(), OP_SELL, 0.1, Bid, 2, 0, 0, “Sell Order”, 0, 0, clrRed);
}
}
//+——————————————————————+
このEAは、”TrendArrows” インディケーターが存在し、適切に機能していることを前提としています。
ストラテジーテスター
MetaTrader 4 (MT4) のエキスパートアドバイザー (EA) のテストを行うには、MT4の組み込み機能である「ストラテジーテスター」を使用します。以下にその手順を説明します。
ストラテジーテスターを使用する手順
MT4を開く: MT4プラットフォームを起動します。
ナビゲーターウィンドウを開く: 画面の左側にある「ナビゲーター」ウィンドウを開きます。もし見当たらない場合は、メニューバーから「表示(V)」→「ナビゲーター(N)」を選択して表示させます。
エキスパートアドバイザーを確認する: ナビゲーターウィンドウ内の「エキスパートアドバイザー」セクションを展開し、テストしたいEAがリストにあることを確認します。もしリストになければ、EAファイル(.mq4または.mq5ファイル)をMT4の「MQL4/Experts」または「MQL5/Experts」ディレクトリにコピーし、MT4を再起動してください。
ストラテジーテスターを開く: メニューバーから「表示(V)」→「ストラテジーテスター(T)」を選択し、ストラテジーテスターウィンドウを開きます。
テスト設定を行う:
エキスパートアドバイザー: ドロップダウンリストからテストしたいEAを選択します。
シンボル: テストする通貨ペアまたは商品を選択します。
期間: テストに使用するチャートの時間枠を選択します。
モデル: テストの精度を選択します。通常、「すべてのティック」が最も正確です。
日付: テストする期間を指定します。特定の日付範囲を指定することも、全期間を選択することもできます。
その他のオプション: スプレッド、最適化の設定など、その他のテスト条件を設定します。
テストを開始する: 設定が完了したら、「開始」ボタンをクリックしてテストを開始します。
結果の確認: テストが完了すると、結果が「結果」タブに表示されます。パフォーマンス指標やグラフを分析して、EAの効果を評価します。
実装例2;移動平均クロスオーバー戦略:
短期と長期の移動平均が交差したときに取引するシンプルな戦略を実装します。
//+——————————————————————+
//| example.mq4 |
//| Copyright 2021, Your Company Name |
//| http://www.yourcompany.com |
//+——————————————————————+
#property copyright “Copyright 2021, Your Company Name”
#property link “http://www.yourcompany.com”
#property version “1.00”
#property strict
// グローバル変数で前回の移動平均を保持
double prevShortMa = 0;
double prevLongMa = 0;
// OnTick関数は、新しい市場データが発生するたびに呼び出されます
void OnTick()
{
// 移動平均の計算
// 移動平均の計算
double shortMa = iMA(Symbol(), PERIOD_H1, 9, 0, MODE_SMA, PRICE_CLOSE, 0); // ‘0’ を追加
double longMa = iMA(Symbol(), PERIOD_H1, 21, 0, MODE_SMA, PRICE_CLOSE, 0); // ‘0’ を追加
// 移動平均のクロスオーバーをチェック
if(shortMa > longMa && prevShortMa <= prevLongMa)
{
// 買い注文のロジック
if(OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, 0, 0, “Buy Order”, 0, clrBlue) < 0)
{
Print(“Buy order failed! Error: “, GetLastError());
}
}
else if(shortMa < longMa && prevShortMa >= prevLongMa)
{
// 売り注文のロジック
if(OrderSend(Symbol(), OP_SELL, 0.1, Bid, 3, 0, 0, “Sell Order”, 0, clrRed) < 0)
{
Print(“Sell order failed! Error: “, GetLastError());
}
}
// 前回の移動平均の値を更新
prevShortMa = shortMa;
prevLongMa = longMa;
}
移動平均の計算:
iMA関数を使用して、短期(9期間)と長期(21期間)の単純移動平均(SMA)を計算します。
クロスオーバーのチェック:
短期移動平均が長期移動平均を上回る(クロスオーバー)場合、買い注文を出します。
短期移動平均が長期移動平均を下回る(クロスアンダー)場合、売り注文を出します。
注文の実行:
OrderSend関数を使用して、市場注文を出します。注文タイプ(買い/売り)、量、価格、スリッページなどのパラメータを指定します。注文が失敗した場合は、エラーメッセージを出力します。
前回の移動平均の更新:
注文判断のために、次のティックで比較するために、現在の移動平均の値をグローバル変数に保存します。
double prevShortMa = 0;: これはprevShortMaという名前の変数を宣言し、それに0という初期値を設定しています。double型は、小数点を含む数値(実数)を保持するためのデータ型です。この変数は、前回の短期移動平均(例えば9期間の移動平均)の値を保存するために使用されます。
double prevLongMa = 0;: これも同様にprevLongMaという名前の変数を宣言し、初期値として0を設定しています。この変数は、前回の長期移動平均(例えば21期間の移動平均)の値を保存するために使用されます。
移動平均クロスオーバー戦略では、短期移動平均と長期移動平均の相対的な位置関係に基づいて取引の決定を行います。具体的には、
短期移動平均が長期移動平均を上回ったときに買い注文を検討し、
短期移動平均が長期移動平均を下回ったときに売り注文を検討します。
これらの判断を行うためには、前回のティックでの短期および長期移動平均の値を知る必要があり、そのためにprevShortMaとprevLongMa変数を使用します。各ティックでこれらの変数を更新し、現在の移動平均の値と比較することで、クロスオーバーが発生したかどうかを判断します。
OnTick()関数を通じて市場の新しいティックデータを受け取ります。この関数は、市場価格が変動するたび(新しい「ティック」があるたび)に呼び出され、EAがその新しいデータに基づいて動作するための場所です。
実装例3:順張りでエントリー25pipsマイナス利益でナンピン
MACDとは
MACDライン
ナンピンロジック
//+——————————————————————+
//| MACD_EA.mq4 |
//| Copyright 2021, Your Company Name |
//| http://www.yourcompany.com |
//+——————————————————————+
#property copyright “Copyright 2021, Your Company Name”
#property link “http://www.yourcompany.com”
#property version “1.00”
#property strict
// ユーザー入力パラメータ
input double TakeProfitPips = 10; // 利益確定のpips
input double DistancePips = 10; // 新しいエントリーまでの距離(pips)
input double MartingalePips = 25; // ナンピンする損失のpips
input int MACD_Fast_EMA = 12; // MACDのための短期EMAの期間
input int MACD_Slow_EMA = 26; // MACDのための長期EMAの期間
input int MACD_Signal_SMA = 9; // MACDシグナルのためのSMAの期間
// グローバル変数
double lastOrderPrice = 0; // 最後の注文価格
int lastOrderType = -1; // 最後の注文の種類
//+——————————————————————+
//| Expert initialization function |
//+——————————————————————+
int OnInit()
{
// 初期化処理
lastOrderPrice = 0;
lastOrderType = -1;
return(INIT_SUCCEEDED);
}
//+——————————————————————+
//| Expert tick function |
//+——————————————————————+
void OnTick()
{
// MACDの計算
double macd_main, macd_signal, macd_hist;
// MACDメインラインの計算
macd_main = iMACD(NULL, 0, MACD_Fast_EMA, MACD_Slow_EMA, MACD_Signal_SMA, PRICE_CLOSE, MODE_MAIN, 0);
// MACDシグナルラインの計算
macd_signal = iMACD(NULL, 0, MACD_Fast_EMA, MACD_Slow_EMA, MACD_Signal_SMA, PRICE_CLOSE, MODE_SIGNAL, 0);
// MACDヒストグラム(MACDとシグナルラインの差)を用いてトレンドを判断
macd_hist = macd_main – macd_signal;
bool isUptrend = macd_hist > 0;
bool isDowntrend = macd_hist < 0;
// 現在の価格を取得(Ask または Bid)
double currentPrice = isUptrend ? Ask : Bid; // トレンドに基づいて価格を選択
// 最後の注文からの距離をチェック
if(lastOrderPrice != 0 && MathAbs(currentPrice – lastOrderPrice) < DistancePips * _Point)
return;
// 上昇トレンドで買いポジション
if(isUptrend)
{
if(OrderSend(Symbol(), OP_BUY, 0.1, currentPrice, 3, 0, 0, “Buy Order”, 0, clrBlue) > 0)
{
lastOrderPrice = currentPrice;
lastOrderType = OP_BUY;
}
}
// 下降トレンドで売りポジション
if(isDowntrend)
{
if(OrderSend(Symbol(), OP_SELL, 0.1, currentPrice, 3, 0, 0, “Sell Order”, 0, clrRed) > 0)
{
lastOrderPrice = currentPrice;
lastOrderType = OP_SELL;
}
}
// ポジション管理およびナンピンのロジック
for(int i = OrdersTotal() – 1; i >= 0; i–)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) && OrderSymbol() == Symbol())
{
// 利益確定のチェック
if(OrderType() == lastOrderType && OrderProfit() > 0 && OrderProfit() >= TakeProfitPips * _Point)
OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 3, clrNONE);
// ナンピンのチェック
if(OrderType() == lastOrderType && OrderProfit() < 0 && MathAbs(OrderProfit()) >= MartingalePips * _Point)
{
if(OrderSend(Symbol(), OrderType(), OrderLots() * 2, currentPrice, 3, 0, 0, “Martingale”, 0, clrRed) > 0)
{
lastOrderPrice = currentPrice;
}
}
}
}
}
//+——————————————————————+
販売用のEAの作成方法
作成者に関する情報を記載する方法
まずは、著作権やEAのです。
新規作成から新たなEAを作成してください。
すると、デフォルトでプロパティという要素が4つ生成されますが、こちらがEAの著作権や詳細の内容になります。
#property copyright “Copyright 2024, MetaQuotes Ltd.”
#property link “https://www.mql5.com”
#property version “1.00”
#property strict
コピーライトはそのまま著作者の情報ですね。
リンクについては、家の販売元や情報を記載しているリンクを記載しましょう。
3つ目のバージョンについては、そのままEAのバージョンですね。
EAの中身は更新して再配布する際などに1.00を例えば1.01などに変更するといった使い方をします。
よく使うプロパティの他の要素としては、
#property description
があります。
EAの詳細な説明を記載する部分ですね。
チャートにEAをセットするとこれらの情報が表示されます。
配布や販売をするときには、こちらの情報を記載することが必須となります。
インジケータを隠す方法
次はEAをバックテストする時に使用しているインジケータを隠す方法について紹介します。
まず、EAはデフォルトの設定でバックテストをビジュアルモードで行った際に、バックテストが終了時に使用しているインジケーターが一覧で出てしまいます。
そのため、第三者から見てこのEAはどの指標をどの期間、どの偏差で使用しているのかといった情報が丸わかりなんですね。
こうなってしまうと、EAを第三者によって解析されてしまうためよくありません。
そのため、バックテストが終了した時にインジケーターが出ないようにしましょう。
その方法とは、OnInit関数に
HideTest Indicators (true);
とするだけです。
こうすることで、インディケーターが表示されないようにすることができます。
EA作成時には必ず入れるようにしてください。
通貨ペアを縛る方法
EAを第三者に配布する際には、通貨ペアを例えばUSD/JPのみでしか使えないようにしたいといったことがあるかと思います。
そういった時に通貨ペア縛りをすると良いでしょう。
以下のコードをOnInit()関数の中に書きます。
if(StringSubstr(Symbol(),0,6)!=”USDJPY”){
Print(“only USDJPY”);
Comment(“only USDJPY”);
return INIT_FAILED;
}
if文のsymbol関数を使います。
通貨ペアを取得することができる関数ですが、USDJPYではないときとしてあげます。symbol()は純粋にそのチャートの通貨ペアを抜き出すのではなく、余計な文字列まで抜け出してしまうのですね。
こういった通貨ペアの時にはsymbol()だけではうまくいきません。そこでStringSubStr()関数を使って、シンボルの前半6文字がUSDJPYの時といった条件にしています。
こちらの関数は第1引数で指定した文字列の第2引数番目から第3引数文字列までを抜き出すという関数です。
つまり、シンボルで取得した文字列の一番初めから6文字抜き出すという意味ですね。
こうすることで、後ろに文字列が付いていても正確に抜き出すことができます。
そして最後にこのEAを動作させたくありませんのでINIT_FAILEDとしてます。
こうすることでチャートからEAが自動で削除されます。
はい、これで通貨ペア縛りを実装することができました。
では実際に確認してみましょう。
現在のチャートはGBPUSDこちらにセットしてみます。
するとonly USDJYというメッセージが出ました。
そしてEAもチャートから自動で削除されています。次にUSDJYに対してやってみましょう。USDJPYチャートをセットするとこのように問題なくチャートがセットされたことがわかると思います。
時間足縛り
今回の時間足縛りには、Period()関数を使います。
if(Period() !=PERIOD_M5){
Print(“Exclusive to the 5-minute chart”);
Comment(“Exclusive to the 5-minute chart”);
return INIT_FAILED;
}
_M5はMT4で標準で搭載されている標準変数になります。
例えばこちらを15分足にしたかったM15。
PrintでメッセージをExclusive to the 5-minute chartとします。
Commentも書いておきます。Commentはチャートに表示されるメッセージです。
これで実装することができました。
では挙動を確認してみましょう。
現在1時間足にセットしていますが、こちらを
セットするとこのようにExclusive to the 5-minute chartというメッセージが出ました。
続いて5分足に変更して再度セットすると、EAがセットされたままになっていることを確認することができました。
使用期限の設定
使用期限とは、その名の通り、この日のこの日時までしかEAを使用することができないようにするといった設定ですね。
//+——————————————————————+
//| Expert initialization function |
//+——————————————————————+
datetime StopTime=D’2024.3.29 13:00′;
停止したい時間をわかりやすいように何年の何月何日ので何分と入力したいのですが、DATETIME型は直接その書式を受け付けていません。
そのため、D’ ‘ することによってDATETIMEに変換することができます。
こちらはそういうものなんだなと覚えておいていただければと思います。
OnInit関数に
if(TimeLocal()>=StopTime){
Print(“Expiration date has passed”);
Comment(“Expiration date has passed”);
return INIT_FAILED;
}
と書いておきましょう。
TimeLocalは使用しているパソコンのローカル時間を取得することができる関数です。
つまり日本時間が
ストップタイムよりも大きい時という条件にしてあげて、
Print (“Expiration date has passed”);
としてあげます。
最後にreturnで INIT_FAILED;を返してあげましょう。
これで実装することができました。
挙動を確認してみましょう。
現在の設定は2024年の3月29日の13時まで許可するという設定になっています。
現在3月20日ですので、うまくできていれば許可されるはずですが。
EAはチャートにセットされたまま成功します。
ではこの状態で一度EAを削除してパラメーターを書き換えてあげます。
3月のではなく1月としてあげましょう。
datetime StopTime=D’2024.1.29 13:00′;
コンパイルして再度チャートにセットします。
するとExpiration date has passedというメッセージとともにEAがチャートから削除されます。
正しく動作していることがわかります。
これで実装することができました。
口座縛りの方法
口座縛りの方法ですが、今回2つの方法を紹介したいと思います。
int Account1=160032537;
if(Account1 !=AccountNumber()){
Print(“Account number is wrong”);
Comment(“Account number is wrong”);
return INIT_FAILED;
}
まず1つ目の方法ですが、まずフィールドにint Accountという変数を用意します。
アカウント1としておきます。
テストのために現在使用しているデモ口座の番号を入力しています。
Account Number ()はEAをセットしているチャートの口座番号を取得する関数ですね。
if(Account1 !=AccountNumber())という条件にしてあげると、指定した口座番号と同じかどうかを判定することができます。
PrintとCommentをccount number is wrongとしておきます。最後にreturn Init FIELDを返してあげます。
挙動を確認してみましょう。
先ほど作成したEAをセットすると、チャートから削除されずに残ります。
では、1度EAを削除して、フィールドから口座番号最後の値を3に変えてあげましょう。
int Account1=160032533;
そうすると。
Account number is wrongと出ました。EAも削除されます。
これで口座番号縛りを実装することができました。
しかし、この方法の問題点としては、ユーザーに配布するために口座番号を聞いて、いちいちこの値を書き換えてコンパイルする必要があるんです
ね。
これはちょっと面倒くさいので、書き換えなくてもよい方法を一つ紹介します。
input int Account2=0;
if(Account2 !=AccountNumber()*3-1234){ //480096377
Print(“Account number is wrong”);
Comment(“Account number is wrong”);
return INIT_FAILED;
}
input int Account2 =0という変数を用意しましょう。
こちらはデフォルト0で大丈夫です。
続いてOn Init関数内で
if (Account2 != Account Number ()) {
ここまでは同じなんですけども、違うのがここからで、適当な式を入れてあげましょう。
例えば、掛ける3引く1234といった式ですね。
これは何をしているのかというと、要するにAccountNumber()*3-1234の値を使用した暗号となっているんですね。
こちらの式はユーザーからは見ることができません。
作成者であるこちらからしか見ることができません。
なのでユーザーに事前に口座番号を聞いておき、この式に当てはめて計算した結果をユーザーに渡す。
そしてユーザーがインプット、つまりパラメーターでアカウント2にその計算結果を入力するという流れになります。
具体的には、現在の口座番号が160032537なので、こちらの番号をユーザーから聞いてこの式に当てはめます。
計算すると、480096377となりました。
この計算結果をこちらからユーザーに伝えてあげます。
ユーザーは受け取った番号を、EAをチャートにセットする際にパラメーターに入力します。
こうすることでEAがセットされます。
この方法の良い点としては、計算した結果を渡すだけでいちいちコンパイルする必要がないという点ですね。