Ver | 変更内容 |
1.01 | スペイン指標対応 |
1.02 | アルゼンチン・ポーランド・ウクライナ指標対応 |
1.03 | MQL5対応 |
1.04 | スェーデン対応 |
1.05 | 新HTML対応 |
Ver | 変更内容 |
1.01 | バー表示数が少ない時に時系列配列外アクセスする不具合修正 |
1.02 | MQL5対応 |
1.03 | MQL5対応による時系列配列アクセス変更で発生した範囲外アクセス不具合修正 |
1.04 | 指標表示の背面オブジェクト再描画処理追加(MT4のみ) |
1.05 | 指標表示範囲を16⇒48時間に拡大。 |
1.06 | 指標時間が未確定でも表示するように変更 |
1.07 | 新HTML対応 |
Q.インジケータIND_EconomicDisplay.ex4がチャート上に表示できません。バグ不具合みたいです。 |
A.まず、EA_EconomicDataRequest_TWEB.ex4を動作させて、csvファイルを生成させます。
データフォルダ\MQL4\FilesにEcoInfo.csvが生成されている事を確認して下さい。 csvファイルが正しく生成された場合は、 というメッセージが表示されます。 IND_EconomicDisplay.ex4はEcoInfo.csvからデータ取得して指標データを表示させている為、csvファイルが無い場合は表示されません。 また指標データは現在時刻から過去7200バー分までしか表示しない為、最後の終値がマーケットクローズから2日経過(1分足の場合)している場合は表示されません。 上記の理由から、バックテスト中も現在時刻から過去7200バー分までしか表示しない為、バックテスト中は基本的に動作しないものとお考え下さい。 それからチャートのヒストリカルデータが過去7200バー分存在しない場合は表示されません。 |
//+------------------------------------------------------------------+ //| EA_EconomicDataRequest_TWEB.mq4 //| Copyright 2015, Created by Yuki. //| http://yukifx.web.fc2.com/ //|―――――――――――――――――――――――――――――――――| //|処理概要:Webサイトから指標データを取得し、Filesフォルダに保存する //+------------------------------------------------------------------+ //| date: Ver: detail //| 15/05/30 1.00 new //| 15/08/27 1.01 !変更 コード置換テーブルにスペイン追加 //| 15/10/20 1.02 !変更 コード置換テーブルにアルゼンチン・ポーランド・ウクライナ追加 //| 15/10/26 1.03 !変更 MQL5対応 //| 16/06/14 1.04 !変更 コード置換テーブルにスウェーデン追加 //| 18/07/26 1.05 !変更 新HTML対応 //| //+------------------------------------------------------------------+ #property copyright "Copyright 2015, Created by Yuki." #property link "http://yukifx.web.fc2.com/" #property version "1.03" #property strict // プログラムの説明 #property description "トレーダーズWEB FXサイト(http://www.traderswebfx.jp/calendar/)から指標スケジュールデータ(HTMLファイル)を取得し、取得したHTMLファイルをCSVファイルに変換出力します。" #ifdef __MQL4__ #property description "ファイルは\"データフォルダ\\MQL4\\Files\"に保存されます。フォルダが読み取り専用になっている場合はエラーになります。" #else #property description "ファイルは\"データフォルダ\\MQL5\\Files\"に保存されます。フォルダが読み取り専用になっている場合はエラーになります。" #endif #property description "このプログラムはEA用です。スレッドの関係でEAプログラムで作成していますが、自動売買は行いません。" #include <local\\local_errorcode_jp.mqh> // エラーコード詳細を日本語で出力する #define ECONOMIC_WEBSITE_ADDRESS "http://www.traderswebfx.jp/calendar/" // Webサイトアドレス #define ECO_SAVE_FILENAME "EcoInfo.html" // 取得したHTMLファイル名 #define ECO_CSV_FILENAME "EcoInfo.csv" // 出力するCSVファイル名 #define ReplaceWordIndex 0 #define SerchWordIndex 1 // コード置換テーブル(上から順に置換する) const string ReplaceCodeTable[][2] = { // 時刻表記無し { ",," ,"<td> </td><td> </td><td> </td>"} // 国名 ,{"乳)" ,"<td class=\"countryicon\"><img src=\"/images/common/icon_newzealand.png\"/>"} ,{"英)" ,"<td class=\"countryicon\"><img src=\"/images/common/icon_uk.png\"/>"} ,{"南)" ,"<td class=\"countryicon\"><img src=\"/images/common/icon_southafrica.png\"/>"} ,{"欧)" ,"<td class=\"countryicon\"><img src=\"/images/common/icon_eu.png\"/>"} ,{"米)" ,"<td class=\"countryicon\"><img src=\"/images/common/icon_america.png\"/>"} ,{"加)" ,"<td class=\"countryicon\"><img src=\"/images/common/icon_canada.png\"/>"} ,{"独)" ,"<td class=\"countryicon\"><img src=\"/images/common/icon_germany.png\"/>"} ,{"豪)" ,"<td class=\"countryicon\"><img src=\"/images/common/icon_australia.png\"/>"} ,{"日)" ,"<td class=\"countryicon\"><img src=\"/images/common/icon_japan.png\"/>"} ,{"土)" ,"<td class=\"countryicon\"><img src=\"/images/common/icon_turkey.png\"/>"} ,{"中)" ,"<td class=\"countryicon\"><img src=\"/images/common/icon_china.png\"/>"} ,{"仏)" ,"<td class=\"countryicon\"><img src=\"/images/common/icon_france.png\"/>"} ,{"希)" ,"<td class=\"countryicon\"><img src=\"/images/common/icon_eu.png\"/>"} ,{"伊)" ,"<td class=\"countryicon\"><img src=\"/images/common/icon_eu.png\"/>"} ,{"瑞)" ,"<td class=\"countryicon\"><img src=\"/images/common/icon_swiss.png\"/>"} ,{"西)" ,"<td class=\"countryicon\"><img src=\"/images/common/icon_eu.png\"/>"} ,{"典)" ,"<td class=\"countryicon\"><img src=\"/images/common/icon_sweden.png\"/>"} // 略名の無い国 ,{"ア)" ,"<td class=\"country\">アルゼンチン"} ,{"ポ)" ,"<td class=\"country\">ポーランド"} ,{"ウ)" ,"<td class=\"country\">ウクライナ"} ,{"メ)" ,"<td class=\"country\">メキシコ"} ,{"ブ)" ,"<td class=\"country\">ブラジル"} ,{"ノ)" ,"<td class=\"country\">ノルウェー"} // HTMLフォーマット変更で追加された項目 ,{"南)" ,"<td class=\"country\">南アフリカ"} ,{"日)" ,"<td class=\"country\">日本"} ,{"豪)" ,"<td class=\"country\">オーストラリア"} ,{"英)" ,"<td class=\"country\">英国"} ,{"米)" ,"<td class=\"country\">米国"} ,{"独)" ,"<td class=\"country\">ドイツ"} ,{"欧)" ,"<td class=\"country\">ユーロ"} ,{"加)" ,"<td class=\"country\">カナダ"} ,{"仏)" ,"<td class=\"country\">フランス"} ,{"香)" ,"<td class=\"country\">香港"} ,{"シ)" ,"<td class=\"country\">シンガポール"} ,{"土)" ,"<td class=\"country\">トルコ"} ,{"乳)" ,"<td class=\"country\">ニュージーランド"} ,{"典)" ,"<td class=\"country\">スウェーデン"} ,{"露)" ,"<td class=\"country\">ロシア"} ,{"瑞)" ,"<td class=\"country\">スイス"} ,{"中)" ,"<td class=\"country\">中国"} ,{"印)" ,"<td class=\"country\">インド"} // セパレート ,{"日," ,"日</td><td>"} ,{"" ,"<td class=\"forecast\">"} ,{"" ,"<td class=\"result\">"} // トップヘッダ ,{"" ,"<th class=\"date\">発表日</th>"} ,{"" ,"<th class=\"time\">時間</th>"} ,{"" ,"<th class=\"countryicon\"></th>"} ,{"" ,"<th class=\"country\">国名</th>"} ,{"" ,"<th class=\"index\">指標名</th>"} ,{"" ,"<th class=\"forecast\">予想</th>"} ,{"" ,"<th class=\"result\">前回の結果</th>"} ,{"" ,"<th class=\"result\">結果</th>"} // ヘッダ ,{"" ,"<th class=\"date\">"} ,{"" ,"<th class=\"time\">"} ,{"" ,"<td class=\"countryicon\">"} ,{"" ,"<th class=\"countryicon\"> </th><th class=\"country\">国名</th><th class=\"index\">"} ,{"" ,"<th class=\"forecast\">"} ,{"" ,"<th class=\"result\">"} // HTMLコード ,{"" ,"<td class=\"index\">"} ,{"" ," "} ,{"" ,"</td><td>"} ,{"" ,"</td>"} ,{"" ,"</th>"} ,{"" ,"<tr>"} ,{"" ,"<td>"} }; sinput bool _Debug = false; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { EventSetTimer(1); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { EventKillTimer(); } //+------------------------------------------------------------------+ //| Timer function | //+------------------------------------------------------------------+ void OnTimer() { static int timer_count = 0; bool temp_ret; temp_ret = false; if ( timer_count >= ( 3600 * 4 ) ) { // 4時間に1度データ取得する timer_count = 0; } if ( timer_count <= 0 ) { temp_ret = EconomicInfoRequest(); // WebサイトからHTMLデータ取得 if ( temp_ret == true ) { EconomicInfoDataCreate(); // HTMLデータをCSVファイル作成 } } timer_count++; } //+------------------------------------------------------------------+ //| 関数名 :EconomicInfoRequest //| 概要 :Webサイト(トレーダーズWEB FXサイト)からHTMLソースコードを //| 取得し、Filesフォルダに保存。 //| 備考 :無し //| ――――――――――――――――――――――――――――――――― //| 戻り値 :bool: 失敗時にfalseを返します //| 引数 :無し //+------------------------------------------------------------------+ bool EconomicInfoRequest(void) { string cookie=NULL,headers; char post[],result[]; int res; string req_url; int filehandle; bool ret; static bool get_success = false; static bool ararted = false; req_url = ECONOMIC_WEBSITE_ADDRESS; ret = false; res = WebRequest( "GET", // HTTPメソッド req_url, // URL cookie, // cookie NULL, // リファラ 5000, // タイムアウト post, // HTTPメッセージ本体 0, // HTTPメッセージサイズ result, // 応答データ配列 headers // 応答ヘッダ ); if( res == -1 ) {// エラーチェック Print("WebRequestエラー。",Get_ComErrorCodeStr( GetLastError()) ); if ( ararted == false ) { ararted = true; MessageBox( "ターミナルオプションの「エキスパートアドバイザータブ」の設定で\n '" +req_url +"' \nのURLを\n「Allow WebRequest for listed URL」のリストに追加して下さい。" ,"HTTPリクエストエラー" ,MB_ICONINFORMATION); } get_success = false; } else { if ( get_success == false ) { PrintFormat("Webサイトデータ取得成功。 取得ファイルサイズ =%d [KB]",ArraySize(result)/1024); } filehandle = FileOpen( ECO_SAVE_FILENAME , FILE_WRITE|FILE_BIN); // 取得データ保存用のファイルを作成 if( filehandle != INVALID_HANDLE) { // ファイルハンドラチェック FileWriteArray(filehandle,result,0,ArraySize(result)); // 取得データをファイルに書き込み FileClose(filehandle); // ファイルハンドラ解放 ret = true; get_success = true; } else { Print("FileOpenエラー。 ",Get_ComErrorCodeStr( GetLastError()) ); } } return ret; } //+------------------------------------------------------------------+ //| 関数名 :EconomicInfoDataCreate //| 概要 :取得したHTMLファイルを開き、指標データのみ抽出する //| 備考 :無し //| ――――――――――――――――――――――――――――――――― //| 戻り値 :bool: 失敗時にfalseを返します //| 引数 :無し //+------------------------------------------------------------------+ bool EconomicInfoDataCreate(void) { int filehandle; // ファイルハンドラ bool ret; ret = false; // filehandle = FileOpen( ECO_SAVE_FILENAME , FILE_READ | FILE_TXT , 0 , CP_UTF8 ); // HTMLファイルを開く // filehandle = FileOpen( ECO_SAVE_FILENAME , FILE_READ | FILE_BIN | FILE_ANSI , 0 , CP_UTF8 ); // HTMLファイルを開く filehandle = FileOpen( ECO_SAVE_FILENAME , FILE_READ | FILE_TXT | FILE_ANSI , 0 , CP_UTF8 ); // HTMLファイルを開く if( filehandle != INVALID_HANDLE) { // ファイルハンドラチェック EcoFileTrim( filehandle ); // 抽出処理関数を呼ぶ FileClose(filehandle); // ファイルクローズ ret = true; } else { Print("FileOpenエラー。 ",Get_ComErrorCodeStr( GetLastError()) ); } return ret; } //+------------------------------------------------------------------+ //| 関数名 :EcoFileTrim //| 概要 :指定したファイルハンドル(取得したHTMLファイル)から、指標データのみ抽出しCSVファイルを作成する //| 備考 :無し //| ――――――――――――――――――――――――――――――――― //| 戻り値 :無し //| 引数 :int in_handle:ファイルハンドラ //+------------------------------------------------------------------+ void EcoFileTrim( int in_handle) { ulong data_st,data_ed; // 指標開始ファイルポンタ、指標衆力ファイルポインタ string get_str_array[]; // 抽出したテキストデータ配列 data_st = SerchWordPointerTXT( in_handle , "<table class=\"scheduletable\">" , 0 , true ); // 指標データ開始ファイルポインタ取得 data_ed = SerchWordPointerTXT( in_handle , "</table>" , data_st , false ); // 指標データ終了ファイルポインタ取得 EcoInfoRowCopy( in_handle , data_st , data_ed , get_str_array); // ファイルから指標データを抽出 RowDataReplace( get_str_array); // 抽出データをCSV形式に変換 ReplaceDataFileWrite( get_str_array); // 変換したデータをCSVファイルへ出力 } //+------------------------------------------------------------------+ //| 関数名 :SerchWordPointerTXT //| 概要 :開いたファイルを指定した文字列で検索し、ファイルポインタを返す //| 備考 :TXT指定で開いたファイルハンドル用 //| ――――――――――――――――――――――――――――――――― //| 戻り値 :検索がヒットしたファイルポインタ //| 引数 :int in_handle :検索するファイルハンドル //| :string in_str :検索する文字列 //| :ulong start_pointer :検索を開始するファイルポインタ位置 //| :bool afterpoint :trueの場合、ヒットした文字列の末尾のポインタを戻り値に返す。falseの場合先頭のポインタを返す。 //+------------------------------------------------------------------+ ulong SerchWordPointerTXT( int in_handle , string in_str , ulong start_pointer , bool afterpoint) { ulong file_size; uchar serch_char[]; ulong icount; bool tempbool; int strlength; string get_str; ulong count_start; ulong ret_pointer; file_size = FileSize(in_handle); // ファイルサイズ取得 strlength = StringLen(in_str); // 検索文字列の文字数取得 count_start = start_pointer; // ファイルポインタ検索開始位置調整 if ( count_start >= file_size ) { count_start = file_size; } if ( count_start < 0 ) { count_start = 0; } ret_pointer = 0; for ( icount = count_start; icount < file_size; icount++ ) { // ファイルの最後まで検索を行う tempbool = FileSeek( in_handle, (long)icount ,SEEK_SET ); // ファイルシーク位置変更 if ( tempbool == false ) { // ファイルシーク失敗時は終了 break; } get_str = FileReadString(in_handle); // 変更したシーク位置のテキスト取得 if ( get_str == in_str ) { // 取得したテキストと検索文字列が一致 ret_pointer = icount; if ( afterpoint == true ) { // オプション ret_pointer = FileTell(in_handle); // 現在(ヒットした文字列の末尾)のファイルポインタを返す } // テスト if ( _Debug == true ) { FileSeek( in_handle, (long)icount ,SEEK_SET ); printf( "1:%d,%s" , ret_pointer , FileReadString(in_handle)); // Print( "1:" + ret_pointer+" "+ FileReadString(in_handle)); FileSeek( in_handle, (long)ret_pointer ,SEEK_SET ); printf( "2:%d, %s" , ret_pointer , FileReadString(in_handle)); // Print( "2:" + ret_pointer+" "+ FileReadString(in_handle)); } break; // 検索文字列がヒットしたら、検索終了 } } return ret_pointer; } //+------------------------------------------------------------------+ //| 関数名 :EcoInfoRowCopy //| 概要 :取得したHTMLデータから、指標データのみ抽出 //| 備考 :無し //| ――――――――――――――――――――――――――――――――― //| 戻り値 :抽出した件数を返す //| 引数 :int in_handle :ファイルハンドラ //| :ulong fp_st :抽出開始位置 //| :ulong fp_ed :抽出終了位置 //| :string &in_str_array[] :出力する文字列配列 //+------------------------------------------------------------------+ int EcoInfoRowCopy( int in_handle , ulong fp_st , ulong fp_ed , string &in_str_array[] ) { bool tempbool; string get_str; string trim_str; int icount; int gcount; long fp_diff; ulong now_fp; const int rev_arraysize = 1000; gcount = 0; fp_diff = (long)fp_ed - (long)fp_st; if ( fp_diff <= 0 ) { printf("【%s】ファイルポインタ取得エラー",__FUNCTION__); return gcount; } ArrayResize(in_str_array,1,rev_arraysize); // 出力する文字列配列の動的配列領域確保 tempbool = FileSeek( in_handle, (long)fp_st ,SEEK_SET ); // ファイルポインタを抽出開始位置に設定 for ( icount = 0; icount < fp_diff; icount++ ) { now_fp = FileTell(in_handle); // 現在のファイルポインタが抽出終了位置に到達したら終了 if ( fp_ed <= now_fp ) { break; } get_str = FileReadString(in_handle); // 現在のファイルポインタから文字列取得 trim_str = StringTrimLeft(get_str); if ( _Debug == true && icount < 20 ) { printf( "生データ[%d]%d [%s]=>[%s]" , __LINE__ , icount, get_str , trim_str); } // 取得した文字列が、HTMLコードのみの場合はスルー if ( trim_str != "<tr>" && trim_str != "</tr>" && trim_str != "<tr class=\"odd\">" ) { if ( icount > 10) { // トップヘッダの10行は書き出ししない ArrayResize(in_str_array,gcount+1,rev_arraysize); // 出力する文字列配列の動的配列領域確保 in_str_array[gcount] = trim_str; // 指標データを動的配列に保存 gcount++; // 抽出件数をインクリメント } } } return gcount; } //+------------------------------------------------------------------+ //| 関数名 :RowDataReplace //| 概要 :抽出した生データをCSV形式に変換 //| 備考 :無し //| ――――――――――――――――――――――――――――――――― //| 戻り値 :無し //| 引数 :string &in_str_array[]:ファイルハンドラ //+------------------------------------------------------------------+ void RowDataReplace( string &in_str_array[] ) { int rowdate_array_max; int tabledate_max; int icount,ccount; string base_str; string change_str; tabledate_max = ArrayRange(ReplaceCodeTable,0); // 変換テーブルの配列数を取得 rowdate_array_max = ArrayRange(in_str_array,0); // 生データの配列数を取得 //テスト // Print(tabledate_max, " ",rowdate_array_max ); for ( icount = 0; icount < rowdate_array_max; icount++ ) { // 生データの配列数分繰り返す base_str = in_str_array[icount]; change_str = StringTrimLeft(base_str); for ( ccount = 0; ccount < tabledate_max; ccount++ ) { // 変換テーブルの配列数分繰り返す // 生データの文字列内に、変換テーブルの文字列があれば置換する StringReplace(change_str , ReplaceCodeTable[ccount][SerchWordIndex],ReplaceCodeTable[ccount][ReplaceWordIndex]); } in_str_array[icount] = change_str; if ( _Debug == true && icount < 20 ) { printf( "置換[%d]%d [%s] => [%s] / [%s]" , __LINE__ , icount, base_str, in_str_array[icount] , change_str); } } } //+------------------------------------------------------------------+ //| 関数名 :ReplaceDataFileWrite //| 概要 :CSV形式に変換したデータを、CSVファイルへ出力する //| 備考 :無し //| ――――――――――――――――――――――――――――――――― //| 戻り値 :無し //| 引数 :string &in_str_array[]:ファイルハンドラ //+------------------------------------------------------------------+ void ReplaceDataFileWrite( string &in_str_array[] ) { int csvhandle; int array_max; int icount; csvhandle = FileOpen(ECO_CSV_FILENAME, FILE_WRITE | FILE_TXT , ',' ,CP_ACP); // CSVファイルを作成する array_max = ArrayRange(in_str_array,0); // 書き込むデータ配列数取得 if( csvhandle != INVALID_HANDLE) { // ファイルハンドラチェック for ( icount = 0; icount < array_max; icount++ ) { // 変換したデータを全て書き込む FileWriteString( csvhandle , in_str_array[icount]+"\n"); } FileClose(csvhandle); // ファイルハンドラ解放 } else { Print("FileOpenエラー。 ",Get_ComErrorCodeStr( GetLastError()) ); } }
//+------------------------------------------------------------------+ //| IND_EconomicDisplay.mq4 | //| Copyright 2015, Created by Yuki. | //| http://yukifx.web.fc2.com/ | //+------------------------------------------------------------------+ //|処理概要:指標データ(CSVファイル)を取得し、チャート上に表示する //+------------------------------------------------------------------+ //| date: Ver: detail //| 15/06/01 1.00 new //| 15/09/21 1.01 !変更 バー表示数が少ない時に時系列配列外アクセスする不具合修正 //| 15/10/26 1.02 !変更 MQL5対応 //| 15/11/12 1.03 !変更 MQL5対応による時系列配列アクセス変更で発生した範囲外アクセス不具合修正 //| 15/12/24 1.04 !変更 指標表示の背面オブジェ追加 EcoDispBackGround_Init //| 16/01/04 1.05 !変更 指標表示範囲を16⇒48時間に拡大 EcoDetailTodayDisp //| !変更 指標表示の背面オブジェクト再描画処理追加。EcoDispBackGround_Init //| 16/01/13 1.06 !変更 指標時間が未確定でも表示するように変更。 EcoDetailTodayDisp,EcoFileRead //| 18/07/26 1.07 !変更 新HTML対応 //| //+------------------------------------------------------------------+ #property copyright "Copyright 2015, Created by Yuki." #property link "http://yukifx.web.fc2.com/" #property version "1.06" #property strict #property indicator_chart_window // プログラムの説明 #property description "トレーダーズWEB FXサイト(http://www.traderswebfx.jp/calendar/)から" #property description "取得した指標スケジュールデータ(CSV変換後のファイル)から、" #property description "直近の指標データを取得し表示します。" #property description "\n別途に指標データを取得するEA(EA_EconomicDataRequest_TWEB.mq4)を動作させる必要があります。" #include <local\\local_errorcode_jp.mqh> // エラーコード詳細を日本語で出力する #include <local\\local_common_jpntime.mqh> // タイムサーバー調整 #define ECO_CSV_FILENAME "EcoInfo.csv" // 出力するCSVファイル名 #define RE_READTIME 4000 // データ読み込み間隔(分解能:1sec) #define OBJ_ECO_HEAD "OEH_" // 指標表示オブジェクト用ヘッダ名 #define OBJ_ECOBG_HEAD "OEBGH_" // 指標背面オブジェクト用ヘッダ名 #define ECODISP_OFFSETDIV 20 // チャート上に表示される指標のオフセットをチャート幅の何分割分にするか enum enum_ecofile_member { ECO_FILE_DAY = 0 , ECO_FILE_TIME , ECO_FILE_EXPECT , ECO_FILE_EXPECT_DUMMY , ECO_FILE_DETAIL , ECO_FILE_FORECAST , ECO_FILE_LASTRESULT , ECO_FILE_RESULT , ECO_FILE_ARRAY_MAX }; static string ReadEcoFileDataArray[][ECO_FILE_ARRAY_MAX]; const int rev_arraysize = 1000; bool FileOpenFlag = false; int DArraySize = -1; sinput int inp_fontsize = 11; // 表示フォントサイズ(7~14) sinput bool inp_ecobg = true; // 指標表示バックグラウンド描画 sinput int inp_comment_xsize = 25; // 枠の横幅上限 sinput bool inp_listoff = false; // 指標リスト非表示 sinput bool inp_disp_offset = false; // 表示オフセット sinput bool inp_debug = false; // デバッグ //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { EventSetTimer(1); ArrayResize(ReadEcoFileDataArray,1,rev_arraysize); // 文字列配列の動的配列領域確保 EcoDispBackGround_Init(true); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { EventKillTimer(); ObjectsDeleteAll( 0 , OBJ_ECO_HEAD); ObjectsDeleteAll( 0 , OBJ_ECOBG_HEAD); Comment(""); } //+------------------------------------------------------------------+ //| 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[]) { return(rates_total); } //+------------------------------------------------------------------+ //| Timer function | //+------------------------------------------------------------------+ void OnTimer() { static int timer_count = RE_READTIME; static int period_count = (Period()*60); bool temp_ret; int ret_count; static bool get_success = false; temp_ret = false; if ( timer_count >= RE_READTIME ) { // 1時間(+α)に1度データ取得する ret_count = EcoFileRead(); DArraySize = ret_count; if ( ret_count > 0 ) { timer_count = 0; FileOpenFlag = true; // test if ( get_success == false ) { Print("指標データ読込完了"); get_success = true; } EcoDetail_AllDisp(); // EcoDetailDisp( 0 , DArraySize ); } else { FileOpenFlag = false; // test printf( "[%d]指標データ読み込み異常:%d", __LINE__ , ret_count ); //Print("指標データ読込異常:" + (string)ret_count); get_success = false; Sleep(50000); } } if ( period_count >= (Period()*60) ) { EcoDetail_AllDisp(); period_count = 0; } timer_count++; period_count++; } //+------------------------------------------------------------------+ //| 関数名 :EcoFileRead //| 概要 : //| 備考 :無し //| ――――――――――――――――――――――――――――――――― //| 戻り値 :読み込んだレコード数を返します //| 引数 :無し //+------------------------------------------------------------------+ int EcoFileRead( void ) { int csvhandle; int icount; int mcount; int arr_count; ulong file_size; string get_str; bool tempbool; string change_date; csvhandle = FileOpen(ECO_CSV_FILENAME, FILE_READ | FILE_CSV , ',' ,CP_ACP); // CSVファイルを開く mcount = 0; arr_count = 0; if ( csvhandle == INVALID_HANDLE ) { // ファイルオープンエラー arr_count = -1; Print("FileOpenエラー。 ",Get_ComErrorCodeStr( GetLastError()) ); Sleep(50000); } else { arr_count = 0; file_size = FileSize(csvhandle); // ファイルサイズ取得 tempbool = FileSeek( csvhandle, 0 ,SEEK_SET ); // ファイルシーク位置設定 ArrayResize(ReadEcoFileDataArray,(int)file_size * ECO_FILE_ARRAY_MAX,rev_arraysize); // 文字列配列の動的配列領域確保 for ( icount = 1; icount < (int)file_size; icount++ ) { // ファイルの最後まで検索を行う get_str = FileReadString(csvhandle); // テスト if ( inp_debug == true && icount < 20) { printf("CSV取得[%d]%d/%d str=[%s]",__LINE__,icount,file_size,get_str); } ReadEcoFileDataArray[arr_count][mcount] = get_str; mcount++; if ( mcount >= ECO_FILE_ARRAY_MAX ) { mcount = 0; arr_count++; } // if ( mcount < ECO_FILE_ARRAY_MAX ) { // ArrayResize(ReadEcoFileDataArray,(int)icount,rev_arraysize); // 文字列配列の動的配列領域確保 // ReadEcoFileDataArray[arr_count][mcount] = get_str; // //テスト // if ( inp_debug == true && icount < 20) { // //printf("CSV配列セット[%d][%d][%d]=[%s]",__LINE__ ,arr_count,mcount,ReadEcoFileDataArray[arr_count][mcount] ); // } // } // // if ( FileIsLineEnding (csvhandle) == true ) { // mcount = 0; // arr_count++; // // } else { // mcount++; // } if ( FileIsEnding(csvhandle) == true ) { break; } } FileClose(csvhandle); // ファイルハンドラ解放 MqlDateTime temp_sttime; TimeToStruct(TimeCurrent() , temp_sttime); // 読み取った日付をMT4用フォーマットに変換 for ( icount = 0 ; icount < arr_count;icount++ ) { if ( ReadEcoFileDataArray[icount][ECO_FILE_DAY] != "" ) { change_date = ReadEcoFileDataArray[icount][ECO_FILE_DAY]; StringReplace(change_date,"月","."); StringReplace(change_date,"日",""); ReadEcoFileDataArray[icount][ECO_FILE_DAY] = StringFormat("%d.%s",temp_sttime.year,change_date); } else { ReadEcoFileDataArray[icount][ECO_FILE_DAY] = ""; } } } if ( inp_debug == true ) { for ( icount = 0 ; icount < 20;icount++ ) { printf("[%d][%d]:DAY=%s,TIME=%s,DETAIL=%s,EX=%s,DUMMY=%s,RESULT=%s,RESULT2=%s",__LINE__,icount ,ReadEcoFileDataArray[icount][ECO_FILE_DAY] ,ReadEcoFileDataArray[icount][ECO_FILE_TIME] ,ReadEcoFileDataArray[icount][ECO_FILE_DETAIL] ,ReadEcoFileDataArray[icount][ECO_FILE_EXPECT] ,ReadEcoFileDataArray[icount][ECO_FILE_EXPECT_DUMMY] ,ReadEcoFileDataArray[icount][ECO_FILE_LASTRESULT] ,ReadEcoFileDataArray[icount][ECO_FILE_RESULT] ); } } return arr_count; } //+------------------------------------------------------------------+ //| EcoDetail_AllDisp //+------------------------------------------------------------------+ void EcoDetail_AllDisp( void ) { int dispbars; int temp_period; int icount; int start_index; temp_period = Period(); if ( temp_period == 0 ) { temp_period = 1; } dispbars = 7200 / Period(); // 過去二日分のバー数 ObjectsDeleteAll( 0 , OBJ_ECO_HEAD); Calculate_JpnTime(0); start_index = -60; if ( Period() == PERIOD_M1 ) { start_index = -180; } // for ( icount = start_index ; icount < dispbars ; icount++ ) { double lowrate; lowrate = Low[iLowest( Symbol(), Period(), MODE_LOW , (int)ChartGetInteger(0,CHART_FIRST_VISIBLE_BAR,0) , 1 )]; //printf( "[%d]%g" , __LINE__ , lowrate ); for ( icount = dispbars ; icount > start_index ; icount-- ) { EcoDetailDisp( icount , DArraySize , lowrate ); } EcoDetailTodayDisp(); } //+------------------------------------------------------------------+ //| EcoDetailDisp //+------------------------------------------------------------------+ void EcoDetailDisp( int in_index , int in_array_size , double in_lowrate) { double dispposi[2]; double dispoffset; datetime temp_nowtime; datetime temp_now_jptime; datetime tempeco_margin1,tempeco_margin2; datetime tempeco_date; string ecoobjst[2]; string tempecodetail; st_jpntime jpntime; int icount; int hit_count; int temp_fontsize; long nowmaxbars; MqlDateTime temp_sttime; // double temp_getrate[]; double temp_getrate; hit_count = 0; nowmaxbars = SeriesInfoInteger(Symbol(),Period(),SERIES_BARS_COUNT); if ( nowmaxbars <= ( in_index + 1) ) { return; } if ( in_index >= 0 ) { temp_nowtime = (datetime)Time[in_index]; } else { temp_nowtime = (datetime)(Time[0] + Period() * 60 * MathAbs(in_index)); } jpntime = Get_TimeJPN(); temp_now_jptime = temp_nowtime + (jpntime.gmt_diff * 3600); temp_fontsize = inp_fontsize; if ( temp_fontsize < 7 ) { temp_fontsize = 7; } if ( temp_fontsize > 14 ) { temp_fontsize = 14; } datetime disp_xtime; double disp_yrate; bool f_bool; static double f_count; f_bool = false; if ( in_index > 0 ) { f_count = 0; } for ( icount = 1 ; icount < in_array_size ; icount++ ) { // 取得した指標分だけ繰り返す(初回分はヘッダなので除く) if ( ReadEcoFileDataArray[icount][ECO_FILE_DAY] == "" ) { continue; // 日付記載が無い場合は次へ } if ( ReadEcoFileDataArray[icount][ECO_FILE_TIME] == "" ) { continue; // 時刻記載が無い場合は次へ } tempeco_date = StringToTime(ReadEcoFileDataArray[icount][ECO_FILE_DAY] + " " + ReadEcoFileDataArray[icount][ECO_FILE_TIME]); TimeToStruct(tempeco_date,temp_sttime); tempeco_margin1 = temp_now_jptime; tempeco_margin2 = temp_now_jptime + ( Period() * 60 ); // 指標名・時間制限表示 if ( tempeco_margin1 <= tempeco_date && tempeco_date <= tempeco_margin2 ) { if ( f_bool == false ) { f_bool = true; f_count++; } // ecoobjst[0] = OBJ_ECO_HEAD + "s" + (string)temp_sttime.day +"D"+ TimeToString(tempeco_date,TIME_MINUTES) +" "+ ReadEcoFileDataArray[icount][ECO_FILE_DETAIL]; ecoobjst[0] = StringFormat( "%ss%dD%s %s",OBJ_ECO_HEAD,temp_sttime.day,TimeToString(tempeco_date,TIME_MINUTES),ReadEcoFileDataArray[icount][ECO_FILE_DETAIL]); ecoobjst[1] = OBJ_ECO_HEAD + "a" + TimeToString(temp_now_jptime,TIME_DATE | TIME_MINUTES); //オブジェクト名の長さは40byteまで。それ以上はエラーになる。(StringLenは全角半角の区別が出来ないので30文字トリムする) if ( StringLen(ecoobjst[0]) >= 31 ) { ecoobjst[0] =StringSubstr( ecoobjst[0] , 0 , 30 ); } if ( in_index >= 0 ) { temp_getrate = High[in_index]; } else { temp_getrate = in_lowrate; } double temppoint; SymbolInfoDouble(Symbol(),SYMBOL_POINT,temppoint); dispposi[0] = temp_getrate + ( 1 * temppoint * 10 ); // dispposi[0] = High[temp_in_index] + ( 1 * Point * 10 ); dispposi[1] = dispposi[0] - ( 1 * temppoint * 10 ); if (ObjectFind( 0, ecoobjst[0] ) == -1 ) { // tempecodetail = ReadEcoFileDataArray[icount][ECO_FILE_TIME] + " " + ReadEcoFileDataArray[icount][ECO_FILE_DETAIL]; tempecodetail = StringFormat( "%s %s%s", ReadEcoFileDataArray[icount][ECO_FILE_TIME] , ReadEcoFileDataArray[icount][ECO_FILE_EXPECT_DUMMY] , ReadEcoFileDataArray[icount][ECO_FILE_DETAIL] ); if ( StringLen(tempecodetail) >= 41 ) { // 念の為40文字トリム tempecodetail =StringSubstr( tempecodetail , 0 , 40 ); } dispoffset = Get_WindowHighLowDiff(); // 重複表示時のオフセット disp_xtime = (temp_nowtime - (3 * Period() * 60) ); disp_yrate = dispposi[0] + ((hit_count + f_count) * dispoffset ); #ifdef __MQL5__ // MT5のみ処理する disp_yrate += ( dispoffset * 1.5); #endif bool right_back; right_back = true; if ( in_index <= 0 ) { ObjectDelete(ecoobjst[0]); right_back = false; } ObjectCreate( 0, ecoobjst[0], OBJ_TEXT,0 , disp_xtime // 表示位置X // ,(Time[temp_in_index] - (3 * Period() * 60) ) // 表示位置X , disp_yrate // 表示位置Y ); // ObjectSetText( 0, ecoobjst[0], tempecodetail , temp_fontsize , "MS ゴシック" , White); ObjectSetString( 0, ecoobjst[0],OBJPROP_TEXT,tempecodetail); ObjectSetInteger( 0, ecoobjst[0],OBJPROP_FONTSIZE,temp_fontsize); ObjectSetString( 0, ecoobjst[0],OBJPROP_FONT,"MS ゴシック"); ObjectSetInteger( 0, ecoobjst[0],OBJPROP_COLOR,clrLime); // ObjectSetInteger( 0, ecoobjst[0],OBJPROP_COLOR,White); ObjectSetInteger( 0, ecoobjst[0],OBJPROP_SELECTABLE,false); ObjectSetInteger( 0, ecoobjst[0],OBJPROP_SELECTED,false); ObjectSetInteger( 0, ecoobjst[0],OBJPROP_HIDDEN,false); if ( in_index >= 0 ) { ObjectSetInteger( 0, ecoobjst[0],OBJPROP_ANCHOR,ANCHOR_CENTER); } else { ObjectSetInteger( 0, ecoobjst[0],OBJPROP_ANCHOR,ANCHOR_LEFT); } ObjectSetInteger( 0, ecoobjst[0],OBJPROP_BACK,right_back); // オブジェクトの背景表示設定 if ( in_index <= 0 ) { ObjectDelete(ecoobjst[1]); } if (ObjectFind( 0, ecoobjst[1]) == -1) { ObjectCreate( 0, ecoobjst[1],OBJ_ARROW,0,temp_nowtime, dispposi[1] + f_count * dispoffset ); // ObjectCreate( ecoobjst[1],OBJ_ARROW,0,Time[temp_in_index], dispposi[1] ); // ObjectSetInteger( 0, ecoobjst[1],OBJPROP_ARROWCODE, SYMBOL_ARROWDOWN); ObjectSetInteger( 0, ecoobjst[1],OBJPROP_ARROWCODE, 242); if ( temp_fontsize == 7 ) { ObjectSetInteger( 0, ecoobjst[1],OBJPROP_WIDTH, 1); } else if ( temp_fontsize == 8 || temp_fontsize == 9 ) { ObjectSetInteger( 0, ecoobjst[1],OBJPROP_WIDTH, 2); } else { ObjectSetInteger( 0, ecoobjst[1],OBJPROP_WIDTH, 3); } ObjectSetInteger( 0, ecoobjst[1],OBJPROP_FONTSIZE,temp_fontsize); ObjectSetInteger( 0, ecoobjst[1],OBJPROP_COLOR,clrLime); // ObjectSetInteger( 0, ecoobjst[1],OBJPROP_COLOR,White); ObjectSetInteger( 0, ecoobjst[1],OBJPROP_SELECTABLE,false); ObjectSetInteger( 0, ecoobjst[1],OBJPROP_SELECTED,false); ObjectSetInteger( 0, ecoobjst[1],OBJPROP_HIDDEN,false); ObjectSetInteger( 0, ecoobjst[1],OBJPROP_ANCHOR,ANCHOR_CENTER); ObjectSetInteger( 0, ecoobjst[1],OBJPROP_BACK,right_back); // オブジェクトの背景表示設定 } hit_count++ ; } } } } //+------------------------------------------------------------------+ //| Get_WindowHighLowDiff | //+------------------------------------------------------------------+ double Get_WindowHighLowDiff( void ) { double temprate; double temp_unitrate; double temp_div; double charthigh,chartlow; long tempdigits; temp_div = ECODISP_OFFSETDIV; charthigh = ChartGetDouble( 0, CHART_PRICE_MAX); chartlow = ChartGetDouble( 0, CHART_PRICE_MIN); temprate = charthigh - chartlow; tempdigits = SymbolInfoInteger(Symbol(),SYMBOL_DIGITS); // temprate = WindowPriceMax(0) - WindowPriceMin(0); // 添え字はチャートインデックス temp_unitrate = NormalizeDouble(temprate / temp_div,(int)tempdigits); // temp_unitrate = NormalizeDouble(temprate / temp_div,Digits); return temp_unitrate; } //+------------------------------------------------------------------+ //| EcoDetailTodayDisp | //+------------------------------------------------------------------+ void EcoDetailTodayDisp( void ) { datetime ecodate, rangesttime , rangeedtime; int remain_stmin, remain_sthour; int intstmin; int icount; string ecoday, eco_marge; string stmin; st_jpntime jpntime; MqlDateTime temp_sttime; string temp_str; int temp_hit; int temp_strlen; int temp_maxstrlen; jpntime = Get_TimeJPN(); rangesttime = jpntime.now_jpntime - 3600 * 2; rangeedtime = jpntime.now_jpntime + 3600 * 48; if ( inp_disp_offset == true ) { eco_marge = "\n\n\n\n"; } else { eco_marge = ""; } temp_hit = 0; temp_maxstrlen = 0; // for ( icount = DArraySize-1; icount >= 0 ; icount-- ) { for ( icount = 0; icount < DArraySize ; icount++ ) { if ( ReadEcoFileDataArray[icount][ECO_FILE_TIME] != "" ) { ecodate = StringToTime( ReadEcoFileDataArray[icount][ECO_FILE_DAY] + " " +ReadEcoFileDataArray[icount][ECO_FILE_TIME] ); } else { ecodate = StringToTime( ReadEcoFileDataArray[icount][ECO_FILE_DAY] + " " +"23:59:00" ); } // ecoday = (string)TimeDay(ecodate); TimeToStruct(ecodate,temp_sttime); ecoday = (string)temp_sttime.day; if ( rangesttime <= ecodate && ecodate <= rangeedtime) { if ( stmin == "-" ) { intstmin = 0; } else { intstmin = (int)StringToInteger(stmin); remain_stmin = (int)((ecodate - jpntime.now_jpntime - (intstmin*60)) / 60); if ( remain_stmin > 0 ) { remain_sthour = remain_stmin / 60; remain_stmin = (int)(MathMod(remain_stmin,60)); } else { remain_sthour = 0; remain_stmin = 0; } } // eco_marge += ecoday + "日 " + TimeToString(StringToTime(ReadEcoFileDataArray[icount][ECO_FILE_TIME]),TIME_MINUTES) + " " ; // eco_marge += ReadEcoFileDataArray[icount][ECO_FILE_DETAIL] + "\n"; if ( ReadEcoFileDataArray[icount][ECO_FILE_TIME] != "" ) { // temp_str = ecoday + "日 " + TimeToString(StringToTime(ReadEcoFileDataArray[icount][ECO_FILE_TIME]),TIME_MINUTES) + " " ; temp_str = StringFormat( "%s日 %s " , ecoday , TimeToString(StringToTime(ReadEcoFileDataArray[icount][ECO_FILE_TIME]),TIME_MINUTES)); } else { temp_str = ecoday + "日 " + "xx:xx" + " " ; } // temp_str += ReadEcoFileDataArray[icount][ECO_FILE_DETAIL] + "\n"; temp_str += StringFormat( "%s%s\n" ,ReadEcoFileDataArray[icount][ECO_FILE_EXPECT_DUMMY],ReadEcoFileDataArray[icount][ECO_FILE_DETAIL]); eco_marge += temp_str; temp_hit++; temp_strlen = StringLen(temp_str); if ( temp_strlen > temp_maxstrlen) { temp_maxstrlen = temp_strlen; } } } if ( inp_listoff == false ) { EcoDispBackGround_Modify( temp_maxstrlen , temp_hit); Comment(eco_marge); } } //+------------------------------------------------------------------+ //| EcoDispBackGround_Init | //+------------------------------------------------------------------+ void EcoDispBackGround_Init( bool ini_init ) { #ifdef __MQL5__ return; // MT5では処理しない #endif if ( inp_listoff != false ) { return; } string objstr; int chart_id = 0; objstr = OBJ_ECOBG_HEAD + "rectangle"; if ( inp_ecobg == false ) { // return; } static int checkcount = 0; if ( ini_init == false ) { checkcount++; if ( checkcount > 100 ) { checkcount = 0; } else { return; } } ObjectCreate(chart_id, objstr, OBJ_RECTANGLE_LABEL, 0 , 0 , 0 ); ObjectSetInteger(chart_id,objstr,OBJPROP_BACK,false); // オブジェクトの背景表示設定 ObjectSetInteger(chart_id,objstr,OBJPROP_SELECTABLE,false); // オブジェクトの選択可否設定 ObjectSetInteger(chart_id,objstr,OBJPROP_SELECTED,false); // オブジェクトの選択状態 ObjectSetInteger(chart_id,objstr,OBJPROP_CORNER,CORNER_LEFT_UPPER); // コーナーアンカー設定 ObjectSetInteger(chart_id,objstr,OBJPROP_XDISTANCE,0); // X座標 if ( inp_disp_offset == true ) { ObjectSetInteger(chart_id,objstr,OBJPROP_YDISTANCE,62); // Y座標 } else { ObjectSetInteger(chart_id,objstr,OBJPROP_YDISTANCE,12); // Y座標 } ObjectSetInteger(chart_id,objstr,OBJPROP_XSIZE,100); // ボタンサイズ幅 ObjectSetInteger(chart_id,objstr,OBJPROP_YSIZE,150); // ボタンサイズ高さ ObjectSetInteger(chart_id,objstr,OBJPROP_BGCOLOR, clrBlack ); // 背景色 ObjectSetInteger(chart_id,objstr,OBJPROP_BORDER_COLOR,clrWhite); // 枠色 ObjectSetInteger(chart_id,objstr,OBJPROP_BORDER_TYPE,BORDER_FLAT); // ボーダータイプ } //+------------------------------------------------------------------+ //| EcoDispBackGround_Modify | //+------------------------------------------------------------------+ void EcoDispBackGround_Modify( int in_x , int in_y) { int fontsize; int chart_id = 0; string objstr; objstr = OBJ_ECOBG_HEAD + "rectangle"; int temp_high; int temp_wide; // const int max_wide = 25; int max_wide; max_wide = inp_comment_xsize; if ( inp_ecobg == false ) { // return; } EcoDispBackGround_Init(false); fontsize = 9; temp_wide = in_x; if ( temp_wide > max_wide ) { temp_wide = max_wide; } temp_high = in_y + (int)(in_y / 3) + 2; ObjectSetInteger(chart_id,objstr,OBJPROP_XSIZE,fontsize * temp_wide ); // ボタンサイズ幅 ObjectSetInteger(chart_id,objstr,OBJPROP_YSIZE,fontsize * temp_high ); // ボタンサイズ高さ }
//+------------------------------------------------------------------+ //| local_common_jpntime.mqh //| Copyright 2015, Created by Yuki. //| http://yukifx.web.fc2.com/ //|―――――――――――――――――――――――――――――――――| //|概要:サーバー時間から日本時間を算出する //+------------------------------------------------------------------+ //| date: Ver: detail //| 15/05/22 1.00 new //| 15/07/31 1.01 !変更 入力パラメータ:タイムゾーン選択の初期値をGMT+2(DST:GMT+3)に変更 //| //+------------------------------------------------------------------+ #ifndef LOCAL_COMMON_TIMER // 2重インクルード対策 #define LOCAL_COMMON_TIMER 1 #property copyright "Copyright 2015, Created by Yuki." #property link "http://yukifx.web.fc2.com/" #define SUMMERTIME_DATETIME_STR ".03.09 02:00" #define WINTERTIME_DATETIME_STR ".11.02 02:00" #define JPN_GMT 9 #define FXCMUK_APIDL_TIMEZONE "2017.6.24" // FXCMUKからAPI_DLしたデータはGMTになる。 enum ENUM_MARKET { MARKET_JPOP = 0, MARKET_JPCL, MARKET_EUOP, MARKET_NYOP, MARKET_FIX, MARKET_NYCL, MARKET_MAX }; // GMT0の時間 static const int GMT0_MarketStartHour[2][MARKET_MAX] = { { 3, 9, 11, 15, 19, 0}, // ウインタータイム { 3, 9, 10, 14, 18, 23} // サマータイム }; static const int MarketStartTime[2][MARKET_MAX] = { { 9, 15, 17, 23, 1, 6}, // ウインタータイム { 9, 15, 16, 22, 0, 5} // サマータイム }; static const string MarketStartTimeStr[MARKET_MAX] = { "JPOP", "JPCL","EUOP", "NYOP", "FIX", "NYCL" }; enum enum_gmt{ // GMTタイプ gmt_0 = 0, // GMT gmt_2 = 2, // GMT+2 (DST:GMT+3) gmt_9 = 9, // GMT+9 gmt_fxcm = 10 // FXCMバックテストGMT -> GMT+2/3 }; struct st_jpntime { // 日本時間構造体 datetime now_jpntime; // 日本時間 datetime now_ustime; // us時間 int gmt_diff; // GMT差分時間 bool dst; // サマータイムbool ENUM_MARKET enum_market; // マーケットENUM // string str_market; // マーケット // string str_dow; // 曜日 }; // 入力パラメータ sinput enum_gmt BASE_GMT_JPY = gmt_2; // タイムゾーン選択 // 静的変数 static st_jpntime St_JPNTime_Data; //+------------------------------------------------------------------+ //| 関数名 :Calculate_JpnTime //| 概要 :指定したバーの時間から日本時間を算出する。 //| 備考 :無し //| ――――――――――――――――――――――――――――――――― //| 戻り値 :無し //| 引数 :int in_nowpos バー数を指定する (0指定は現在時間) //+------------------------------------------------------------------+ void Calculate_JpnTime( int in_nowpos ) { datetime now_jptime; // 日本時間 datetime summerinday; // サマータイム開始日時 datetime summeroutday; // サマータイム終了日時 datetime servertime; // サーバー時間 int diff_gmt; // 内部GMT差分 int local_nowbar; bool dst_season; // サマータイム期間判定結果 true:サマータイム false:ウインタータイム enum_gmt select_gmt; // タイムゾーン datetime changetime; changetime = StrToTime(FXCMUK_APIDL_TIMEZONE); datetime ustime; local_nowbar = in_nowpos; if ( Bars <= in_nowpos ) { local_nowbar = Bars - 1; } // if ( 0 > in_nowpos ) { // local_nowbar = 0; // } if ( 0 > in_nowpos ) { ustime = Time[0] + ( MathAbs(in_nowpos) * Period() * 60 ); } else { ustime = Time[local_nowbar]; } if ( BASE_GMT_JPY == gmt_fxcm ) { if ( ustime < changetime) { select_gmt = gmt_0; } else { select_gmt = gmt_2; } } else { select_gmt = BASE_GMT_JPY; } diff_gmt = JPN_GMT - (int)select_gmt; servertime = ustime; // チャート上の時間取得 now_jptime = (servertime) + (diff_gmt * 3600); // 日本時間を算出 // GMT判定後の日本時間算出 summerinday = StrToTime((string)TimeYear(servertime) + SUMMERTIME_DATETIME_STR); // サマータイム開始日時 summeroutday = StrToTime((string)TimeYear(servertime) + WINTERTIME_DATETIME_STR); // サマータイム終了日時 if ( servertime >= summerinday && servertime <= summeroutday ) { // サマータイム dst_season = true; } else { // ウインタータイム dst_season = false; } dst_season = CheckDST(dst_season , servertime ); if ( dst_season == true ) { if ( select_gmt == gmt_2 ) { // サマータイムで影響するGMTのみ処理する if ( select_gmt == gmt_2 ) { // サマータイムはGMTを1時間スライドする diff_gmt = diff_gmt - 1 ; now_jptime = (servertime) + ( diff_gmt * 3600); } } } St_JPNTime_Data.gmt_diff = diff_gmt; St_JPNTime_Data.now_jpntime = now_jptime; St_JPNTime_Data.now_ustime = ustime; St_JPNTime_Data.dst = dst_season; St_JPNTime_Data.enum_market = GetMarketEnum( now_jptime , dst_season ); // St_JPNTime_Data.str_market = GetMarketStr( St_JPNTime_Data.enum_market ); // St_JPNTime_Data.str_dow = GetDowString( now_jptime ); ////デバッグプリント用 // printf("チャート時間[%d]:%s, 日本時間:%s , GMT:%d , サマータイム:%d", // in_nowpos, // TimeToStr(servertime,TIME_DATE|TIME_SECONDS), // TimeToStr(St_JPNTime_Data.now_jpntime,TIME_DATE|TIME_SECONDS), // St_JPNTime_Data.gmt_diff, // dst_season // ); } //+------------------------------------------------------------------+ //| 関数名 :CheckDST //| 概要 :サーバー時間のサマータイムは週末に切り替わるのでその対応 //| 備考 :3/9~11/2以外の場合に変更する //| ――――――――――――――――――――――――――――――――― //| 戻り値 :bool DST(true:サマータイム) //| 引数 :bool DST判定結果 //+------------------------------------------------------------------+ bool CheckDST( bool in_dst , datetime in_time ) { bool retsdt; retsdt = in_dst; // 2015 - 2016年の冬時間タイム if ( StrToTime("2015.11.01 00:00") < in_time && in_time <= StrToTime("2016.3.13 00:00") ) { retsdt = false; } // 2016 - 2017年の夏時間タイム if ( StrToTime("2016.3.13 00:00") < in_time && in_time <= StrToTime("2016.11.6 00:00") ) { retsdt = true; } // 2016 - 2017年の冬時間タイム if ( StrToTime("2016.11.06 00:00") < in_time && in_time <= StrToTime("2017.3.12 00:00") ) { retsdt = false; } // 2017 - 2018年の夏時間タイム if ( StrToTime("2017.3.12 00:00") < in_time && in_time <= StrToTime("2017.11.5 00:00") ) { retsdt = true; } // 2017 - 2018年の冬時間タイム if ( StrToTime("2017.11.05 00:00") < in_time && in_time <= StrToTime("2018.3.11 00:00") ) { retsdt = false; } return retsdt; } // ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ //+------------------------------------------------------------------+ //| 関数名 :Get_TimeJPN //| 概要 :算出済みの日本時間を返します。 //| 備考 :事前にCommon_TimeCulate()を呼び出す必要があります。 //| ――――――――――――――――――――――――――――――――― //| 戻り値 :st_jpntime 日本時間構造体の値を返します //| 引数 :無し //+------------------------------------------------------------------+ st_jpntime Get_TimeJPN( void ) { return St_JPNTime_Data; } //+------------------------------------------------------------------+ //| 関数名 :Cov_Us2JpnTime //| 概要 :USTIMEをJPNTIMEに変換 //| 備考 : //| ――――――――――――――――――――――――――――――――― //| 戻り値 :datetime JPNTIME //| 引数 :無し //+------------------------------------------------------------------+ datetime Cov_Us2JpnTime( datetime in_ustime ) { datetime jptime; jptime = in_ustime + ( St_JPNTime_Data.gmt_diff * 3600 ); return jptime; } //+------------------------------------------------------------------+ //| 関数名 :Cov_Us2JpnTime //| 概要 :USTIMEをJPNTIMEに変換 //| 備考 : //| ――――――――――――――――――――――――――――――――― //| 戻り値 :datetime JPNTIME //| 引数 :無し //+------------------------------------------------------------------+ datetime Cov_Jpn2UsTime( datetime in_jptime ) { datetime ustime; ustime = in_jptime - ( St_JPNTime_Data.gmt_diff * 3600 ); return ustime; } //+------------------------------------------------------------------+ //| マーケットENUM取得 //+------------------------------------------------------------------+ ENUM_MARKET GetMarketEnum( datetime in_date , bool in_dst ) { ENUM_MARKET ret = MARKET_JPOP; int now_hour = TimeHour(in_date); if ( MarketStartTime[in_dst][MARKET_FIX] <= now_hour && now_hour < MarketStartTime[in_dst][MARKET_NYCL] ) { ret = MARKET_FIX; } if ( MarketStartTime[in_dst][MARKET_NYCL] <= now_hour && now_hour < MarketStartTime[in_dst][MARKET_JPOP] ) { ret = MARKET_NYCL; } if ( MarketStartTime[in_dst][MARKET_JPOP] <= now_hour && now_hour < MarketStartTime[in_dst][MARKET_JPCL] ) { ret = MARKET_JPOP; } if ( MarketStartTime[in_dst][MARKET_JPCL] <= now_hour && now_hour < MarketStartTime[in_dst][MARKET_EUOP] ) { ret = MARKET_JPCL; } if ( MarketStartTime[in_dst][MARKET_EUOP] <= now_hour && now_hour < MarketStartTime[in_dst][MARKET_NYOP] ) { ret = MARKET_EUOP; } if ( MarketStartTime[in_dst][MARKET_NYOP] <= now_hour ) { ret = MARKET_NYOP; } if ( MarketStartTime[in_dst][MARKET_FIX] > now_hour ) { ret = MARKET_NYOP; } return ret; } //+------------------------------------------------------------------+ //| マーケット名 //+------------------------------------------------------------------+ string GetMarketStr( ENUM_MARKET in_market ) { string ret = MarketStartTimeStr[0]; if ( in_market < MARKET_MAX ) { ret = MarketStartTimeStr[in_market]; } return ret; } //+------------------------------------------------------------------+ //| 曜日取得 //+------------------------------------------------------------------+ string GetDowString( datetime in_date ) { int tempdow; string jpndow; tempdow = TimeDayOfWeek( in_date ); switch (tempdow) { case SUNDAY: jpndow = "日"; break; case MONDAY: jpndow = "月"; break; case TUESDAY: jpndow = "火"; break; case WEDNESDAY: jpndow = "水"; break; case THURSDAY: jpndow = "木"; break; case FRIDAY: jpndow = "金"; break; case SATURDAY: jpndow = "土"; break; } return jpndow; } #endif