政策金利を表示するインジケーターを作ってみた

こんにちは
fx-on.comエンジニアの岩淵です。
今夜はFOMCですね。
正直結果が気になって仕事どころではありません
今夜のFOMCでは政策金利が大きなテーマでしょう。
そこで今日は政策金利を表示するインジケーターの作り方をご紹介します。
試しにこのアドレスにアクセスしてみると、政策金利関連の処理がJavaScriptでズラッと書いてあります。
ザッと見ていくと外部ファイルから政策金利のデータを引っ張ってきていそうな、set_bankrate関数がありました。
set_bankrate関数がアクセスしているアドレスにアクセスしてみると、政策金利のデータと思われるJSON形式のデータが表示されます。
内容を見ていると、国ごとにミリ秒単位の日付と政策金利がセットになって並んでいる感じでしょう。
まずはこのページに表示されている内容をMQL4から取得しましょう。
MQL4からwebへアクセスするには、標準搭載のWebRequest関数を使用する方法と、wininet.dllから幾つかの関数を読み込んで自分で処理を書く方法があります。
WebRequest関数の欠点として、インジケーターファイルから使用できないのと、MT4のオプションから指定したサイトにしかアクセス出来ないという問題がありますので、今回はwininet.dllを読み込んで処理を作成します。
入手したデータは現在1つの文字列型変数に格納されているため、このままでは使い物になりません。
データを切り分けて、目的の数値を取得する必要があります。
プログラミング言語によっては標準でJSON形式を成型する関数があるのですが、
MQL4には残念ながら存在しません。
そこでGoogle先生の出番です。
調べてみると、MQL4用のJSON成型クラスを作った方がいるようです。
http://www.lordy.co.nf/mql4/
今回はこの方が作成したhash.mqhとjson.mqhをお借りして続きを作成していきます。
コンパイルしたらエラーが出たので少しだけ弄ったのと、hash.mqhのincludeをjson.mqhから行うよう変更した点以外はそのままです。
json.mqhの中身は正直複雑すぎて理解できませんでしたが、
公開されているサンプルを参考に試行錯誤した結果、
外為どっとコムから取得したデータはJSONArrayを使うと上手く日付や政策金利に切り分けて取得できるようです。
作るもの
指定した国の政策金利をチャートに表示するインジケーター実装
MQL4プログラマーの皆さんはご存知の通り、政策金利はMQL4の標準関数には用意されておりません。 まずは政策金利を入手する必要があります。 入手の方法として考えられるのは、次の2パターンです。 1.どこかのwebサイトから引っ張ってくる 2.事前にcsvなどのファイルを用意しておき、プログラムからファイルを読み込む 政策金利を調べてcsvファイルにまとめる作業が面倒なので、 今回はwebから入手する方法で実装したいと思います。 「政策金利」でググッて一番上に出てきた、「外為どっとコム」様のこちらのページから政策金利を入手します。 http://www.gaitame.com/market/seisakukinri.html サイトのコードを見てみると、いかにも政策金利の処理をしていそうな一文がありました。
試しにこのアドレスにアクセスしてみると、政策金利関連の処理がJavaScriptでズラッと書いてあります。
ザッと見ていくと外部ファイルから政策金利のデータを引っ張ってきていそうな、set_bankrate関数がありました。
set_bankrate関数がアクセスしているアドレスにアクセスしてみると、政策金利のデータと思われるJSON形式のデータが表示されます。
内容を見ていると、国ごとにミリ秒単位の日付と政策金利がセットになって並んでいる感じでしょう。
まずはこのページに表示されている内容をMQL4から取得しましょう。
MQL4からwebへアクセスするには、標準搭載のWebRequest関数を使用する方法と、wininet.dllから幾つかの関数を読み込んで自分で処理を書く方法があります。
WebRequest関数の欠点として、インジケーターファイルから使用できないのと、MT4のオプションから指定したサイトにしかアクセス出来ないという問題がありますので、今回はwininet.dllを読み込んで処理を作成します。
#import "wininet.dll"
int InternetOpenW(string agent, int accessType, string proxyName, string proxyByPass, int flags);
int InternetConnectW(int internet, string serverName, int port, string userName, string password, int service, int flags, int context);
int HttpOpenRequestW(int connect, string verb, string objectName, string version, string referer, int acceptType, uint flags, int context);
int HttpAddRequestHeadersW(int, string, int, int);
bool HttpSendRequestW(int hRequest,string &lpszHeaders,int dwHeadersLength,uchar &lpOptional[],int dwOptionalLength);
bool HttpQueryInfoW(int request, int infoLevel, string &buffer, int &size, int &index);
int InternetOpenUrlW(int internetSession, string url, string header, int headerLength, int flags, int context);
int InternetReadFile(int, uchar &arr[], int, int &byte);
int InternetCloseHandle(int winINet);
#import
string AccessToInternetGetMethod(string url, string parameters=NULL){
string result = "";
int byte_size = 0;
uchar receive[1024];
if(get!=NULL){
url = StringConcatenate(url, "?", get);
}
int inet = InternetOpenW("MetaTrader 4 Terminal", 0, "0", "0", 0);
if(inet == 0) return(NULL);
int handle = InternetOpenUrlW(inet, url, NULL, 0, 0, 0);
while(InternetReadFile(handle, receive, 1024, byte_size)){
if(byte_size <= 0) break;
result += CharArrayToString(receive, 0, byte_size, CP_UTF8);
}
InternetCloseHandle(handle);
InternetCloseHandle(inet);
return(result);
}
試しにこの関数を実行してテキストファイルに書きだしてみると、ちゃんとデータを取得できているのが分かります。(処理は割愛いたします)
入手したデータは現在1つの文字列型変数に格納されているため、このままでは使い物になりません。
データを切り分けて、目的の数値を取得する必要があります。
プログラミング言語によっては標準でJSON形式を成型する関数があるのですが、
MQL4には残念ながら存在しません。
そこでGoogle先生の出番です。
調べてみると、MQL4用のJSON成型クラスを作った方がいるようです。
http://www.lordy.co.nf/mql4/
今回はこの方が作成したhash.mqhとjson.mqhをお借りして続きを作成していきます。
コンパイルしたらエラーが出たので少しだけ弄ったのと、hash.mqhのincludeをjson.mqhから行うよう変更した点以外はそのままです。
json.mqhの中身は正直複雑すぎて理解できませんでしたが、
公開されているサンプルを参考に試行錯誤した結果、
外為どっとコムから取得したデータはJSONArrayを使うと上手く日付や政策金利に切り分けて取得できるようです。
string url = "http://www.gaitame.com/market/seisakukinri_all.txt";
string data = AccessToInternetGetMethod(url, NULL) ;
JSONParser *parser = new JSONParser();
JSONValue *jv = parser.parse(data);
if(jv == NULL) Print("error:" + (string)parser.getErrorCode() + parser.getErrorMessage());
else{
if(jv.isArray()){
JSONArray *ja = jv;
}
}
日付と政策金利が取得できるようになれば、あとはfor文やif文を駆使してゴリゴリ書いていくだけです。
最終的に出来上がったコードがこちら。
#property strict
#property indicator_buffers 1
#property indicator_separate_window
#property indicator_level1 0.00
#property indicator_maximum 12.5
#property indicator_minimum -1.50
#property indicator_color1 Red
#include <json.mqh>
#import "wininet.dll"
int InternetOpenW(string agent, int accessType, string proxyName, string proxyByPass, int flags);
int InternetConnectW(int internet, string serverName, int port, string userName, string password, int service, int flags, int context);
int HttpOpenRequestW(int connect, string verb, string objectName, string version, string referer, int acceptType, uint flags, int context);
int HttpAddRequestHeadersW(int, string, int, int);
bool HttpSendRequestW(int hRequest,string &lpszHeaders,int dwHeadersLength,uchar &lpOptional[],int dwOptionalLength);
bool HttpQueryInfoW(int request, int infoLevel, string &buffer, int &size, int &index);
int InternetOpenUrlW(int internetSession, string url, string header, int headerLength, int flags, int context);
int InternetReadFile(int, uchar &arr[], int, int &byte);
int InternetCloseHandle(int winINet);
#import
double PolicyInterestRate[];
enum ENUM_COUNTRY{
Japan=0, // 日本
USA=1, // 米国
Euro=2, // 欧州
UK=3, // 英国
Canada=4, // カナダ
Australi=5, // 豪州
NZ=6, // NZ
Switzerland=7, // スイス
HongKong=8, // 香港
SouthAfrica=9, // 南ア
China=10, // 中国
Turkey=11, // トルコ
Norway=12, // ノルウェー
Sweden=13, // スウェーデン
Mexico=14 // メキシコ
};
extern ENUM_COUNTRY country = 0; //国
int OnInit(){
IndicatorDigits(2);
IndicatorShortName(MQLInfoString(MQL_PROGRAM_NAME) + " " + EnumCounttyToString(country));
SetIndexBuffer(0, PolicyInterestRate);
return(INIT_SUCCEEDED);
}
bool access = true;
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(access){
access = false;
getJsonData();
}
return(rates_total);
}
string AccessToInternetGetMethod(string url, string parameters=NULL){
string result = "";
int byte_size = 0;
uchar receive[1024];
if(parameters != NULL && parameters != ""){
url = StringConcatenate(url, "?", parameters);
}
int inet = InternetOpenW("MetaTrader 4 Terminal", 0, "0", "0", 0);
if(inet == 0) return(NULL);
int handle = InternetOpenUrlW(inet, url, NULL, 0, 0, 0);
while(InternetReadFile(handle, receive, 1024, byte_size)){
if(byte_size <= 0) break;
result += CharArrayToString(receive, 0, byte_size, CP_UTF8);
}
InternetCloseHandle(handle);
InternetCloseHandle(inet);
return(result);
}
void getJsonData(){
string url = "http://www.gaitame.com/market/seisakukinri_all.txt";
string data = AccessToInternetGetMethod(url, NULL) ;
JSONParser *parser = new JSONParser();
JSONValue *jv = parser.parse(data);
if(jv == NULL) Print("error:" + (string)parser.getErrorCode() + parser.getErrorMessage());
else{
if(jv.isArray()){
JSONArray *ja = jv;
for(int i = Bars-1; i >= 0; i--){
for(int j = 0; j < ja.getArray(country).size(); j++){
if(Time[i] < ja.getArray(country).getArray(j).getLong(0) / 1000){
break;
}
else{
if(j < ja.getArray(country).size() - 1){
if(Time[i] < ja.getArray(country).getArray(j + 1).getLong(0) / 1000){
PolicyInterestRate[i] = ja.getArray(country).getArray(j).getDouble(1);
break;
}
}
}
}
}
}
delete jv;
}
delete parser;
}
string EnumCounttyToString(ENUM_COUNTRY val){
if(val == 0) return("日本");
else if(val == 1) return("米国");
else if(val == 2) return("欧州");
else if(val == 3) return("英国");
else if(val == 4) return("カナダ");
else if(val == 5) return("豪州");
else if(val == 6) return("NZ");
else if(val == 7) return("スイス");
else if(val == 8) return("香港");
else if(val == 9) return("南ア");
else if(val == 10) return("中国");
else if(val == 11) return("トルコ");
else if(val == 12) return("ノルウェー");
else if(val == 13) return("スウェーデン");
else if(val == 14) return("メキシコ");
return("");
}
実際にチャートに表示してみるとこんな感じです。
AUDJPYの月足チャートに日本(赤)とオーストラリア(黄色)の政策金利を表示しております。
国を選択できるようになっており、好きな国の金利を比較することができます。
頻繁に変わる数値ではないので、更新処理は考えておりません。



