MQL5で日付と時刻を扱う方法を学ぶ
はじめに
時間の重要性、そしてそれが取引の意思決定や結果にどのような影響を与えるかは、金融市場関係者は誰も隠していないことです。MQL5 (MetaQuotes Language 5)は、日付と時間を効果的に扱うための素晴らしいソリューションを提供しています。この記事では、MQL5プログラミング言語でこのトピックの最も重要な側面を理解した後、取引システムの一部としてコード化できる多くのアプリケーションを通じて、この重要なトピックをどのように扱うことができるかを見ていきます。
この記事で取り上げるのは以下のトピックです。
これらのトピックを読むことで、作成するソフトウェアの一部として、MQL5でdatetime型のデータを使用できるようになることが期待されています。前述したように、datetimeトピックは取引において非常に重要なトピックであり、トレーダーや取引システム開発者として、その扱い方を理解する必要があります。この記事が役に立ち、読者がそのトピックについて、あるいは少なくとも関連するトピックについて洞察を得られることを願っています。datetime型
MQL5のdatetime変数型は、日付と時刻のデータをUnix時間で並び替えるのに使用されます。Unix時間は1970年1月1日からの経過秒数です。例えば、2023年1月1日00:00:00GMTの日付をUnix時間に変換すると、1672531200秒になります。したがって、タイムスタンプは特定の日付とUnix時間(1970年1月1日)との間の秒数です。また、以下のように、既知の可読時間と比較した秒単位の時間も見ることができます。既知の可読時間 | 秒 |
---|---|
1年 | 31556926秒 |
1ヶ月 | 2629743秒 |
1週間 | 604800秒 |
1日 | 86400秒 |
1時間 | 3600秒 |
Unix時間のトピックについては興味深い情報があります。さらに詳しく読みたい場合は、ウィキペディアの「UNIX時間」の記事をご覧ください。
特定の日付と時刻を決定する必要がある場合があります。これは、次の形式と同じように単一引用符で囲まれたD文字で始まるdatetime定数を使用することで非常に簡単におこなうことができます。
D'yyyy.mm.ddhh:mm:ss'
または
D'dd.mm.yyyyhh:mm:ss'
以下のMQL5リファレンスでの例は、この文脈で有用なガイドとなります。
datetime NY=D'2015.01.01 00:00'; // Time of beginning of year 2015 datetime d1=D'1980.07.19 12:30:27'; // Year Month Day Hours Minutes Seconds datetime d2=D'19.07.1980 12:30:27'; // Equal to D'1980.07.19 12:30:27'; datetime d3=D'19.07.1980 12'; // Equal to D'1980.07.19 12:00:00' datetime d4=D'01.01.2004'; // Equal to D'01.01.2004 00:00:00' datetime compilation_date=__DATE__; // Compilation date datetime compilation_date_time=__DATETIME__; // Compilation date and time datetime compilation_time=__DATETIME__-__DATE__;// Compilation time //--- Examples of declarations after which compiler warnings will be returned datetime warning1=D'12:30:27'; // Equal to D'[date of compilation] 12:30:27' datetime warning2=D''; // Equal to __DATETIME__
以下は、コンパイル後の出力結果です。
datetime型が日付と時刻の値を秒数で保持することはこれまで理解してきた通りです。これにより、日付と時刻の値の比較や操作が容易になります。以下は、日付と時刻の値を扱うときにできることの例です。
- 日付と時刻の値の比較
- 日付と時刻の値の加減算
- 時間と文字列間の変換
日付と時刻の値の比較
2つの時刻と日付の値があり、他の目的のためにそれらを比較する必要がある場合、MQL5ではすべての値に対して変数を作成し、その結果に基づいてアクションを実行するためにそれらを比較することでそれをおこなうことができます。以下はその例です。
ユーザーが2つの日付と時刻の値を入力し、一方が他方より古い場合に特定の結果を得たいとします。例えばprint文で、入力1の値が入力2の値より大きい場合は、「Input one is a recent time」というメッセージを出力し、入力1の値が入力2の値より小さい場合は、「Input two is a recent time」というメッセージを出力する必要があるとします。
以下はそのためのコードです。
//+------------------------------------------------------------------+ //| dateTimeCompare.mq5 | //+------------------------------------------------------------------+ input datetime inpDate1 = D'2023.09.01 00:00'; input datetime inpDate2 = D'2023.09.30 00:00'; //+------------------------------------------------------------------+ void OnTick() { if(inpDate1>inpDate2) { Print("Input one is a recent time"); } else if(inpDate1<inpDate2) { Print("Input two is a recent time"); } } //+------------------------------------------------------------------+
このコードをコンパイルした後、日付と時刻の入力値を以下のように設定すると、以下のようになります。
見てわかるように、1番目は2番目よりも古いため、結果は次のようになります。
最初の入力を2番目の入力より新しいものに変更した場合、以下のようになります。
これまでの入力設定によれば、以下のような結果が得られるはずです。
先のコード例は、日付と時刻を比較として扱う方法のサンプルです。
日付と時刻の値の加減算
また、日付と時刻の値に足し算や引き算をすることもできます。例えば、次のような2つの日付と時刻の値があるとします。
D'2023.09.0100:00'
D'2023.09.3000:00'
ここで、最初の値に1日を加算し、2番目の値から1日を減算する必要があります。1日は86400秒に相当します。これら2つのトランザクションの後、次の新しい値が得られます。
D'2023.09.0200:00'
D'2023.09.2900:00'
以下のコードは、これらのトランザクションをどのようにコード化するかについてのものです。
//+------------------------------------------------------------------+ //| dateTimeManipulate.mq5 | //+------------------------------------------------------------------+ input datetime oldDate = D'2023.09.01 00:00'; input datetime newDate = D'2023.09.30 00:00'; //+------------------------------------------------------------------+ void OnTick() { datetime addToDate = oldDate+86400; Print("Result of date addition - ",addToDate); datetime subtractFromDate = newDate-86400; Print("Result of date subtraction - ",subtractFromDate); } //+------------------------------------------------------------------+
実行した結果は次のようになります。
時間と文字列間の変換
日付と時刻の値の型を変換する必要がある場合があります。現時点では、文字列と日付時刻の間の変換を処理できる関数には、TimeToStringかStringToTimeの2つがあります。ここでは、次のコードと同じようなケースにどのように対処できるかの例を見てみましょう。
//+------------------------------------------------------------------+ //| dateTimeConvert.mq5 | //+------------------------------------------------------------------+ input datetime oldDate = D'2023.09.01 00:00'; input string newDate = "2023.09.30 00:00"; //+------------------------------------------------------------------+ void OnTick() { string newOldDate = TimeToString(oldDate); datetime newNewDate = StringToTime(newDate); Print("Time To String - ",newOldDate); Print("String To Time - ",newNewDate); } //+------------------------------------------------------------------+
このコードを取引端末で実行すると、TimeToStringを変換する関数とStringToTimeを変換する関数のそれぞれの戻り値が以下のように表示されます。
一般的に言って、MQL5でdatetime型に関するすべての操作については以下で理解できます。
- currentTime:現在の時刻を戻す
- 値同士の比較:論理的には、時間比較の確認にこの操作を使用
- 日時データの操作:足し算と引き算
- 日付と時刻の書式設定
MqlDateTime構造体
この部分では、MqlDateTime構造体について学びます。この変数には、日付と時刻、または日時のデータを格納することができます。以下はMQL5のリファレンスにあるのと同じ構造体です。
struct MqlDateTime { int year; // Year int mon; // Month int day; // Day int hour; // Hour int min; // Minutes int sec; // Seconds int day_of_week; // Day of week (0-Sunday, 1-Monday, ... ,6-Saturday) int day_of_year; // Day number of the year (January 1st is assigned the number value of zero) };
見ての通り、int型変数のフィールドが8つ含まれています。
この構造体でTimeToStruct関数を使い、日付時刻の値をMqlDateTimeの変数に変換します。
- dt:日時
- dt_struct:値を採用するための構造体
この関数はブール値を返します。
MqlDateTime構造体の変数をdatetime値に変換するには、StructToTime関数も使用できます。パラメータはdt_structのみです。秒数を含むdatetime型を返します。
このMqlDateTime構造体の例を以下に示します。
D'2023.10.1007:07:07'のような入力値がある場合は、MqlDateTimeを使用する必要があります。それは次のコードでできます。
//+------------------------------------------------------------------+ //| MqlDateTime.mq5 | //+------------------------------------------------------------------+ input datetime dtData = D'2023.10.10 07:07:07'; void OnTick() { MqlDateTime timeStruct; TimeToStruct(dtData,timeStruct); int year = timeStruct.year; Print("year: ",year); Print("====================="); int month = timeStruct.mon; Print("month: ",month); Print("====================="); int day = timeStruct.day; Print("day: ",day); Print("====================="); int hour = timeStruct.hour; Print("hour: ",hour); Print("====================="); int minute = timeStruct.min; Print("minute: ",minute); Print("====================="); int second = timeStruct.sec; Print("second: ",second); Print("====================="); int dayofWeek = timeStruct.day_of_week; Print("dayofWeek: ",dayofWeek); Print("====================="); int dayofYear = timeStruct.day_of_year; Print("dayofYear: ",dayofYear); } //+------------------------------------------------------------------+
このEAを実行すると、以下のようなメッセージが出力されます。
入力として1未満を使用した場合の月または日のデフォルト値は01であり、入力がこの最大値より大きい場合、月の最大デフォルト値は12、日は31であることに注意してください。時のデフォルト値は最小0または最大23、分のデフォルト値は最小0または最大59です。
OnTimer()イベント
この部分では、OnTimer()イベントハンドラとは何か、そしてその使い方を学びます。指定した秒数ごとにコードや取引戦略を実行する必要がある場合に使用できます。したがって、特定の時間間隔で特定のアクションを実行させたい場合は、OnTimer()イベントハンドラにコードを記述すればよくなります。
OnTimer()イベントハンドラは、パラメータのないvoid型で、必要であればコードに追加することができます。使用するには、OnInit()で、EventSetTimer()関数にsecondsパラメータを指定してタイマー間隔を設定する必要があります。
int OnInit() { EventSetTimer(60); }
先の例では、OnTimer()イベントハンドラ内のコードが60秒ごとに実行されます。
OnTimer()イベント内でコードの実行を停止する必要がある場合は、onDeinit()イベントハンドラまたはクラスデストラクタでvoid EventKillTimer()関数を使用します。
NewBarアプリケーション
このアプリケーションでは、EAのような他のファイルで使用できるクラスや関数を保持するインクルードファイルを作成し、新しいバーがある場合に「A new bar painted」というメッセージを表示して、報告することを目的とします。
まず、以下の手順でインクルードファイルを作成します。ここでインクルードファイルを作成する主な意味は、初心者の場合、多くのプロジェクトで使用でき、開発者としてプロフェッショナルに働けるファイルを構築することを学び、適応するということです。
2つのprivate変数(現在のバーの時間を格納するtime[]と、最新のバーの時間を格納するlastTime)を持つCNewBarクラスを宣言します。次の2つのパラメータを持つbool型newBarCheck関数の宣言を含めます。
- symbol(string型)
- timeFrame(ENUM_TIMEFRAMES型)
class CNewBar { private: datetime time[], lastTime; public: void CNewBar(); bool newBarCheck(string symbol, ENUM_TIMEFRAMES timeFrame); };
時間配列を系列に設定します。
void CNewBar::CNewBar(void) { ArraySetAsSeries(time,true); }
2つのパラメータ(symbolとtimeFrame)を持つnewBarCheck関数を宣言します。この関数では、新しいバーがあるかどうかを確認し、bool型の値を戻します。
bool CNewBar::newBarCheck(string symbol, ENUM_TIMEFRAMES timeFrame)
関数本体は、新しいバーがあるかどうかを確認し、firstとnewBarの2つのbool変数をデフォルトのfalse値で作成します。
bool firstCheck = false; bool newBar = false;
指定された銘柄と期間のペアのバーの開始時刻のtime_array履歴データを指定された量取得するために、CopyTime関数の最初の位置で呼び出すバリアントを使用します。パラメータは次の通りです。
- symbol_name:銘柄の名前
- timeframe:時間枠(ENIM_TIMEFRAMESから)
- start_pos:開始位置(0)
- count:コピーするデータ(2)
- time_array[]:開いている時間をコピーする配列
CopyTime(symbol,timeFrame,0,2,time);lastTimeクラス変数を確認します;。最初のチェックであれば、lastTime変数の値は0となり、firstCheck変数はtrueとなります。
if(lastTime == 0) { firstCheck = true; }
time[0]がlastTimeより大きいかどうかを確認し、firstCheckの値がfalseに等しいかどうかを確認します。newBarがtrueになると、lastTimeはtime[0]と同じ値になります。
if(time[0] > lastTime) { if(firstCheck == false) { newBar = true; } lastTime = time[0]; }
bool型のnewBarの値を返します。
return(newBar);
以下は、このインクルードファイルのすべてのコードを1つのブロックにまとめたものです。
//+------------------------------------------------------------------+ //| newBar.mqh | //+------------------------------------------------------------------+ class CNewBar { private: datetime time[], lastTime; public: void CNewBar(); bool newBarCheck(string symbol, ENUM_TIMEFRAMES timeFrame); }; //+------------------------------------------------------------------+ void CNewBar::CNewBar(void) { ArraySetAsSeries(time,true); } //+------------------------------------------------------------------+ bool CNewBar::newBarCheck(string symbol, ENUM_TIMEFRAMES timeFrame) { bool firstCheck = false; bool newBar = false; CopyTime(symbol,timeFrame,0,2,time); if(lastTime == 0) { firstCheck = true; } if(time[0] > lastTime) { if(firstCheck == false) { newBar = true; } lastTime = time[0]; } return(newBar); } //+------------------------------------------------------------------+
MQL5のオブジェクト指向プログラミング(OOP)とクラスについてもっと知りたい方は、以前の「MQL5オブジェクト指向プログラミング(OOP)について」稿が役に立つかもしれません。
さて、インクルードファイルを作成した後、新しいバーを検出し、「A new bar painted, you can trade」というメッセージを表示するEAを作成します。まず、作成したインクルードファイルをプリプロセッサ#includeを使ってEAコードにインクルードします。
#include <dateTime.mqh>
CNewBarクラスのオブジェクトを宣言します。
CNewBar NewBar;
新しいバーが描かれたときに取引する(true)かしない(false)かを選択する入力として、bool変数を作成します。
bool newBarTrade=true;
その後、OnTick()の部分で、newBarのbool変数をデフォルトのtrue値で作成し、別の整数barShift変数をデフォルトの0値で作成します。
bool newBar=true; int barShift=0;
newBarTradeがtrueの場合、newBarはNewbarobject.newBarCheckに等しく、パラメータは現在の銘柄と現在の時間枠で、barShiftは1に等しくなります。
if(newBarTrade==true) { newBar = NewBar.newBarCheck(Symbol(),Period()); barShift=1; }
newBarがtrueに等しいかどうかを確認します。trueの場合、新しいバーが生成されたことを意味するので、「A new bar painted, you can trade」というメッセージを出力します。
if(newBar==true) { Print("A new bar painted, you can trade"); }
以下は、このアプリケーションのコードを1つのブロックにまとめたものです。
//+------------------------------------------------------------------+ //| newBar.mq5 | //+------------------------------------------------------------------+ #include <dateTime.mqh> CNewBar NewBar; bool newBarTrade=true; //+------------------------------------------------------------------+ void OnTick() { bool newBar=true; int barShift=0; if(newBarTrade==true) { newBar = NewBar.newBarCheck(Symbol(),Period()); barShift=1; } if(newBar==true) { Print("A new bar painted, you can trade"); } } //+------------------------------------------------------------------+
このEAを実行した後、新しいバーが生成されると、次のような結果が得られます。
このコードは、新しいバーが描画されたときに、例えば取引を開始するなど、ご自分の戦略に従ってアクションを変更するために開発することができますが、この記事ではコードの主なアイデアを理解するための簡単なコードを共有しており、必要に応じて開発することができます。
timeFilterアプリケーション
timeFilterまたは指定された期間に基づいて取引を許可または防止するために使用できるフィルタアプリケーションを作成する必要があります。作成したインクルードファイルにCTimeFilterという新しいクラスを追加し、3つのパラメータ(startTime、endTime、localTime、デフォルト値はfalse)を持つpublic bool timeCheck関数を作成します。
class CTimeFilter { public: bool timeCheck(datetime startTime, datetime endTime, bool localTime = false); };
timeCheck関数の本体を作成します。startTimeがendTime以上であるか、またはendTimeがendTime以上であるかによって、入力されたデータが間違っているかどうかを確認し、間違っている場合は、エラーアラート「Error:Invalid Time input」とfalseを返します。
if(startTime >= endTime) { Alert("Error: Invalid Time input"); return(false); }
datetime型のcurrentTime変数を作成し、localTimeがtrueかどうかを確認します。trueならばTimeLocal()をcurrentTimeに代入し、そうでなければTimeCurrent()をcurrentTimeに代入します。
datetime currentTime; if(localTime == true) { currentTime = TimeLocal(); } else currentTime = TimeCurrent();
bool型のtimeFilterActive変数をデフォルトのfalse値で作成します。currentTimeがstartTime以上であると同時にendTime未満であれば、timeFilterActiveをtrueとして返します。
bool timeFilterActive = false; if(currentTime >= startTime && currentTime < endTime) { timeFilterActive = true; } return(timeFilterActive);
インクルードファイルのすべてのコードを1ブロックにまとめると、次のようになります。
class CTimeFilter { public: bool timeCheck(datetime startTime, datetime endTime, bool localTime = false); }; bool CTimeFilter::timeCheck(datetime startTime, datetime endTime, bool localTime = false) { if(startTime >= endTime) { Alert("Error: Invalid Time input"); return(false); } datetime currentTime; if(localTime == true) { currentTime = TimeLocal(); } else currentTime = TimeCurrent(); bool timeFilterActive = false; if(currentTime >= startTime && currentTime < endTime) { timeFilterActive = true; } return(timeFilterActive); }
インクルードファイルを作成したら、次のステップでtimeFilterApp EAを作成します。
dateTimeファイルをインクルードして、その内容を使用します。
#include <dateTime.mqh>
StartTimeとEndTimeという2つのdatetime変数を入力値として作成します。
input datetime StartTime = D'2023.10.10 10:00'; input datetime EndTime = D'2023.10.10 17:00';
グローバルスコープにfilterという名前のオブジェクトを作成します。
CTimeFilter filter;
OnTick()で、timeFilterActiveを作成し、そのパラメータをfilter.timeCheckに代入します。
bool timeFilterActive = filter.timeCheck(StartTime,EndTime,false);
「Trading is active based on time filte「」または「Trading is inactive based on time filter」というメッセージを受け取って、timeFilterActiveがtrueかどうかを確認できます。
if(timeFilterActive == true) { Print("Trading is active based on time filter"); } else Print("Trading is inactive based on time filter");
以下は1つのブロック内の完全なコードです。
//+------------------------------------------------------------------+ //| timeFilterApp.mq5 | //+------------------------------------------------------------------+ #include <dateTime.mqh> input datetime StartTime = D'2023.10.10 10:00'; input datetime EndTime = D'2023.10.10 17:00'; CTimeFilter filter; void OnTick() { bool timeFilterActive = filter.timeCheck(StartTime,EndTime,false); if(timeFilterActive == true) { Print("Trading is active based on time filter"); } else Print("Trading is inactive based on time filter"); }
このアプリケーションを実行すると、結果は、入力された時間に従って3つのいずれかになります。
アクティブ時間の場合:
非アクティブ時間の場合:
誤入力の場合:
インクルードファイルを使わない方法もあります。次がその手順です。
開始時刻と分、終了時刻と分について、4つの入力int変数をグローバルに作成します。
input int TimeStartHour = 10 ; input int TimeStartMin = 0; input int TimeEndHour = 17; input int TimeEndMin = 0 ;
OnTick()では、日付と時刻のデータを含むMqlDateTime関数を使用してstructTime変数を作成します。
MqlDateTime structTime;
作成したstructTime変数をTimeCurrent関数に渡します。
TimeCurrent(structTime);
秒を0に、時、分を開始時間に設定します。
structTime.sec = 0;
structTime.hour = TimeStartHour;
structTime.min = TimeStartMin;
datetime型のtimeStart変数を作成し、構造体変数MqlDateTimeをdatetime型の値に変換するStructToTime関数にstructTimeを渡し、それをtimeStart変数に代入します。
datetime timeStart = StructToTime(structTime);
終了時刻に時間と分を設定します。
structTime.hour = TimeEndHour; structTime.min = TimeEndMin;
timeStartと同様にtimeEnd変数を作成します。
datetime timeEnd = StructToTime(structTime);
取引可能時間を決定するbool型isTime変数を作成します。
bool isTime = TimeCurrent() >= timeStart && TimeCurrent() < timeEnd;
誤入力時には、エラーメッセージを出力します。
if(TimeStartHour >= TimeEndHour) { Print("Error: Invalid Time input"); }
取引時間の条件を設定します。
if(isTime==true) { Print("Trading is active based on time filter"); } else Print("Trading is inactive based on time filter");
以下は、1つのブロック内の完全なコードです。
//+------------------------------------------------------------------+ //| timeFilterApp2.mq5 | //+------------------------------------------------------------------+ input int TimeStartHour = 10; input int TimeStartMin = 0; input int TimeEndHour = 17; input int TimeEndMin = 0; //+------------------------------------------------------------------+ void OnTick() { MqlDateTime structTime; TimeCurrent(structTime); structTime.sec = 0; structTime.hour = TimeStartHour; structTime.min = TimeStartMin; datetime timeStart = StructToTime(structTime); structTime.hour = TimeEndHour; structTime.min = TimeEndMin; datetime timeEnd = StructToTime(structTime); bool isTime = TimeCurrent() >= timeStart && TimeCurrent() < timeEnd; if(TimeStartHour >= TimeEndHour) { Print("Error: Invalid Time input"); } if(isTime==true) { Print("Trading is active based on time filter"); } else Print("Trading is inactive based on time filter"); } //+------------------------------------------------------------------+
このコードを実行すると、以下のような結果が得られます。
アクティブの場合:
非アクティブ取引時間の場合:
誤入力の場合:
tradeAtTimeアプリケーション
例えば、特定の時間帯にのみ取引をおこなう必要がある場合、この時間帯を取引可能時間として設定する必要があります。以下が手順です。
デフォルト値「10:00」の入力文字列型変数openTimeをグローバルに作成します。
input string openTime="10:00";
datetime型lastTime変数を作成します。
datetime lastTime;
OnTick()で、datatime型のdtOpenTime変数を作成し、openTimeのStringToTime値を代入します。
datetime dtOpenTime=StringToTime(openTime);
取引可能時間の条件をチェックし、最後の取引可能時間がdtOpenTimeと等しくないと同時にtimeCurrent()がdtOpenTimeより大きい場合、lastTimeの値をdtOpenTimeで更新し、「Now is the allowed time to trade」というメッセージを表示します。このメッセージは、指定された時刻に一度だけ出力されます。
if(lastTime !=dtOpenTime && TimeCurrent()>dtOpenTime) { lastTime=dtOpenTime; Print("Now is the allowed time to trade"); }
以下が完全なコードです。
//+------------------------------------------------------------------+ //| tradeAtTime.mq5 | //+------------------------------------------------------------------+ input string openTime="10:00"; datetime lastTime; //+------------------------------------------------------------------+ void OnTick() { datetime dtOpenTime=StringToTime(openTime); if(lastTime !=dtOpenTime && TimeCurrent()>dtOpenTime) { lastTime=dtOpenTime; Print("Now is the allowed time to trade"); } } //+------------------------------------------------------------------+
このコードを実行すると、次が表示されます。
結論
MQL5で時間を考慮したカスタマイズをおこなうために、datetimeとは何か、そしてどのように日付と時間を扱うことができるかを理解していただけたと思います。MQL5におけるdatetimeとその使用方法を確認し、さらにこの重要なトピックの理解を深めるために、簡単なアプリケーションにそれを適用しました。これらのアプリケーションは、日付と時刻を効果的に処理するために、どのようなソフトウェアにも組み込むことができます。以下のトピックを理解できたと思います。
- datetime型
- MqlDateTime構造体
- OnTimerイベント
- NewBarアプリケーション
- timeFilterアプリケーション
- tradeAtTimeアプリケーション
取引で日付と時刻に関して使用できるアプリケーションは数多くあり、それらすべてについて言及することはできませんが、トピックの基本を理解することで、必要なアプリケーションに適用できます。
この記事が役に立ち、読者のMQL5プログラミング言語の「学習の旅」に役立つことを願っています。この記事が役に立ち、より多くの記事をご覧になりたい場合は、私の出版物をご確認ください。最も人気のあるテクニカル指標に基づいて取引システムを作成する方法に関する記事や、MQL5プログラミング言語を学ぶという文脈で他の記事を見つけることができます。
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/13466
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索