fc2ブログ

blue(GBPJPY)の新バージョンは色々と楽しめそう!

先週からblue(GBPJPY)を購入して運用し始めていたのですが、今週バージョンアップがあったので、新バージョンをテスト中です。
※自動売買の許可をOFFにしていたのに気付かず、コミュニティでドタバタした投稿をしてしまい、開発者のARATA様にはご迷惑お掛けしました。
 
今回のバージョンアップでパラメータが大幅に増えていますが、それらは後日検討するとして・・・
 
@とりあえずバックテストしてみた結果
デフォルトパラメータ使用、始値のみ、証拠金50万円、円口座、
10年間、Alpariヒストリカルデータ、スプレッド3.0pips
blue_default_param.png
 
@とりあえずパラメータを振ってみた結果
blue_param_160331.png
 
とても自由度が高いように感じます!!
新バージョンアップは他の通貨ペアでも動かせるようですので、パラメータ次第では、ひょっとすると全方位対応が出来てしまうかもしれませんね。
 
なお、今回は始値のみ使用したバックテストなので、トレーリングストップの効きが悪くなりますが、4時間足で動くEAなので大まかな傾向は全ティックと変わらないと思います。
 
パラメータが多い分だけ検証にも時間が掛かるので、半年くらい掛けて試すつもりです。
※こういう時に限って忙しくて、夜以降の時間しか確保できない… (/_;)
 
最大ポジション1個の利大損小EA
blue(GBPJPY)
blue(GBPJPY) | fx-on.com
 

テーマ : FX(外国為替証拠金取引)
ジャンル : 株式・投資・マネー

【JForex】配信レートの小数部の桁数を取得する関数は、便利でもあり不便でもある、、、

FX注文時の利食い/損切り計算で必須となる、レート配信の小数部の桁数取得ですが、JForexの場合はPips計算に特化しています。
https://www.dukascopy.com/client/javadoc/
 
> Enum Instrument
>> int getPipScale()
   Returns decimal place count of one pip for the currency pair
>> double getPipValue()
   Returns value of one pip for this currency pair
 
Instrumentは通貨ペアを保持する列挙型です。
> public Instrument instrument = Instrument.USDJPY;
また、MQLとは違ってJavaの列挙型はクラスなので、メソッドを持っていたりします。
 
利食い/損切りをpipsで指定している場合、
> double takeProfitPips = 100.0;
> double takeProfitValue = takeProfitPips * instrument.getPipValue();
とすれば計算出来るので便利です。
うん、便利なのですが・・・
 
注文時のレート指定に有効桁数以上の数値が含まれる場合、エラーになることがあります。(MT4/MQLと同じですね)
 
例えばUSDJPYの場合、配信レートの小数部有効桁数は3桁です。
USDJPYの注文時に、例えば2進数演算の影響で 113.33300000001 など小数部が多くなったレートを指定するとサーバーがエラーを返す事があるので、有効桁数の丸め処理が必要になります。(MQLのNormalizeDouble関数相当)
しかし、USDJPYのinstrument.getPipScale()は2を返しますので、有効桁数としては使えません。
どこを探しても、小数部有効桁数を取得するメソッドがInstrumentにありません…
 
一応、インターフェースIFinancialInstrumentにgetTickScale()というメソッドが用意されているのですが、Instrumentから取得出来ないのは納得いかないです。
それに、IFinancialInstrumentをInstrumentにimplementsするとしても、結局メソッドは実装しなきゃならないし、、、面倒すぎる!
 
とりあえず試行錯誤したところ、IContextからIFinancialInstrumentProvider経由でIFinancialInstrumentへ繋げられるようなので、今はそれで我慢しています。
 
まぁ、気になると言えば、IContext.getFinancialInstrumentProvider()の説明が、
> NOTE: Under development
となっている所ですかね。知らんがなw
 
これで、MQLのDigits()相当の関数は実装できることが分かったのですが、ストラテジー実装までの道程は長いなぁ…
 
ソースコート(onStartして終わるストラテジー)
jforex_geiTickScale.png
 
実行結果
jforex_geiTickScale_result.png
 
※小数部の有効桁数を導き出すのに、
  > instrument.getPipScale() + 1;
 としているソースコートも見掛けました。
 FXのストラテジーとしては、この実装でも問題なさそうです。
 

テーマ : FX(外国為替証拠金取引)
ジャンル : 株式・投資・マネー

【国内MT4業者でもGOLD!】fx-onに出品しました!

fx-onに出品した「カコテン iRSI (typeDI) XAUUSD」のフォワード計測が始まりました。
1ヶ月程度の審査で問題なければ、販売開始となります。
 
kako10_iRSI_DI_XAUUSD_H1.png
 
バックテストについては商品ページ掲載のとおりですが、さてさて、興味はフォワードがどうなるかですね!
ゲムトレードに出品した姉妹品「カコテン iRSI (typeDI) XAUUSD」は、いきなりストップロスからのスタートでしたから… orz...
 
運用可能業者は、海外のMT4業者ではGoldとSilverを扱っているところが多いのですが、国内MT4業者になると東岳証券しか扱っていません。
 
東岳証券の場合、XAUUSDのスプレッドは5.0pips原則固定ですので、期待できると思っています。
 


 
なお、XAUUSDのpipsは分かりづらいのですが、損切り270pips=-270ドル(約-30,500円)、利食い510pips=510ドル(約57,600円)となります。
 

テーマ : FX(外国為替証拠金取引)
ジャンル : 株式・投資・マネー

JForexって日本語メール送れないのね・・・

Dukascopyが日本に進出したことだし、自動売買を是とするnekonoteとしてはJForexもやってみたいなぁ・・・と思って手を出したら躓いたオチ。。。
 
自作EAのトレード部分を移植して動かしてみたら、MT4インジケーターとJForexインジケーターに微妙な相違がありそう?(バックテストの損益曲線の形が少し異なる)
この調査には時間が掛かりそうですが、今は時間が足りな~い(泣)
 
とりあえず調査は後回しにして、自作ロジックではいつも実装しているメール送信機能を試してみたら、今度は日本語が文字化け orz...
jforex_mail_japanese_ng.png
 
さらに連続してメールが送れない orz...
jforex_mail_request.png
 
docを再確認したら、1分制限なんてものがあったのか…
https://www.dukascopy.com/client/javadoc/
jforex_sendMail_doc.png
 
JavaMailをインストールすれば良いのだろうけど、Dukascopy提供予定の無料VPSでは使えないだろうし・・・でも今のまま複数のストラテジーを動かしたら、メール送信制限に引っかかるの目に見えてるし・・・メール送信機能は諦めるかぁ・・・(挫折気味)
 
今回のソースはこちら(onStartして終わるストラテジー)
jforex_mail_test.png
 
なお、メール送信元は
jforex_mail_from.png
 
となっていました。
 

テーマ : FX(外国為替証拠金取引)
ジャンル : 株式・投資・マネー

【VPS】WIN-VPS.comのVPSは順調に稼動していましたが・・・

稼動当初はゴタゴタしたWIN-VPS.comですが、その後は順調に稼働していました。
ただ1つの問題を除いて…
 
MT4からメールが送れません。。。
 
win-vps_mt4_smtp_err.png
 
SSLのポート465も、SSLではないポート587も、他ドメインのメールアカウントも、全てエラーになってしまいます。
WIN-VPS.comのサポートに英語で問い合わせれば直るのかもしれませんが、英語苦手だし、ロシアの業者ということでサービス提供の継続に不安を感じてしまうので、今回は1ヶ月で諦めることにしました。
 
ただ、国内最安値のWEBKEEPERSのVPSよりは、WIN-VPS.comのVPSのほうが、安定性もコストも優れていたと思います。
一般の方にはあまりお勧め出来ませんが、仮想サーバーに詳しい方であれば、WIN-VPS.comは選択肢としてアリですね。
 

テーマ : FX(外国為替証拠金取引)
ジャンル : 株式・投資・マネー

【マイナス金利の弊害】銀行口座の金利は表面上マイナスにならなくても、実質ではマイナスに転落する可能性大!

日銀は「個人向けの預金金利がマイナスになることは無い」という見解を出していますが、大嘘です。
表面上はマイナスにならなくても、実質的にはマイナス金利に転落する可能性大です。
以下、参考となる記事を見ながら検証してみます。
 
まず、日銀を除く銀行の場合、預金口座にマイナス金利を課すことは、確かに困難らしいです。
ただ、手数料名目で徴収は可能だとも・・・
下記の記事を参照して下さい。
 
(参考記事)ZUU online
マイナス金利で「銀行預金から金利分が差し引かれる」のか?
 
証券会社の口座預り金などで運用されているMRFは、今のところマイナス金利からは逃れられそうですが、銀行口座の他に運用先が無くて困っているとも解釈できます。
 
(参考記事)Yahoo!Japan ニュース
なぜMRFがマイナス金利適用外となったのか
 
実際、行き先を失ったお金が集まってきた銀行は大変みたいです。
 
(参考記事)NHK ONLINE
マイナス金利 金融機関の負担1か月で約18億円
 
先ほどのYahoo!Japanの記事と合わせると、銀行の中でも信託銀行では、1ヶ月で7~8億円もの負担があったということになります。
お金を預かれば預かるほど負担が膨らむという、理不尽さ・・・
 
それじゃ銀行はどうするか?
マイナス金利をそのまま負担する銀行は少ないと思います。(銀行は営利企業です)
最初のZUU onlineの記事にもありましたが、マイナス金利分を手数料等の名目で顧客に転嫁することになるでしょう。
 
よって、銀行口座の実質的な預金金利(手数料込み)はマイナスに転落する可能性が高いと言えます。
 
実質って・・・携帯会社の販売と同じですよね・・・
今後は「実質金利は○%!」などの比較が流行るのでしょうか?
 

テーマ : FX(外国為替証拠金取引)
ジャンル : 株式・投資・マネー

週足・月足が正しく作成されるように、PeriodConverterを改造する

前回の記事で、MT4添付スクリプト「PeriodConverter」と、これを元にした派生スクリプトでは、週足・月足が正しく作成されないことを説明しました。
 
このまま放置するのも何なので、PeriodConverterを改造して、週足・月足が正しく作成されるようにしてみましょう。
ついでに、ALL版に改造しちゃいます!
 
ポイントは3点、
 ・最終足が保存されるようにする
 ・週足、月足のOpen時間を正しく計算する
 ・月足はOpen~Closeの期間が不定になることに留意する
と、ALL版のループ処理になります。
 
PeriodConverterAllEx.mq4
//+------------------------------------------------------------------+
//|                                              PeriodConverter.mq4 |
//|                   Copyright 2006-2015, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright   "2006-2015, MetaQuotes Software Corp."
#property link        "http://www.mql4.com"
#property description "Period Converter to updated format of history base"
#property strict
//#property show_inputs

//input int InpPeriodMultiplier=3; // Period multiplier factor
int InpPeriodMultiplier;
int       ExtHandle=-1;
//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   datetime time0;
   ulong    last_fpos=0;
   long     last_volume=0;
   int      i,start_pos,periodseconds;
   int      cnt=0;
//---- History header
   int      file_version=401;
   string   c_copyright;
   string   c_symbol=Symbol();
//   int      i_period=Period()*InpPeriodMultiplier;
   int      i_period;
   int      i_digits=Digits;
   int      i_unused[13];
   MqlRates rate;
   int      all_period[8]={5,15,30,60,240,1440,10080,43200};
   int      j;
   datetime next_bar_time;
//---
   if(Period() != PERIOD_M1)
     {
      Print("Start Period Must be M1.");
      return;
     }
//---
   for(j=0;j<ArraySize(all_period);j++)
     {
      InpPeriodMultiplier=all_period[j];
      i_period=Period()*InpPeriodMultiplier;
      Comment(i_period,"min. write...");
//---
   ExtHandle=FileOpenHistory(c_symbol+(string)i_period+".hst",FILE_BIN|FILE_WRITE|FILE_SHARE_WRITE|FILE_SHARE_READ|FILE_ANSI);
   if(ExtHandle<0)
      return;
   c_copyright="(C)opyright 2003, MetaQuotes Software Corp.";
   ArrayInitialize(i_unused,0);
//--- write history file header
   FileWriteInteger(ExtHandle,file_version,LONG_VALUE);
   FileWriteString(ExtHandle,c_copyright,64);
   FileWriteString(ExtHandle,c_symbol,12);
   FileWriteInteger(ExtHandle,i_period,LONG_VALUE);
   FileWriteInteger(ExtHandle,i_digits,LONG_VALUE);
   FileWriteInteger(ExtHandle,0,LONG_VALUE);
   FileWriteInteger(ExtHandle,0,LONG_VALUE);
   FileWriteArray(ExtHandle,i_unused,0,13);
//--- write history file
   periodseconds=i_period*60;
   start_pos=Bars-1;
   rate.open=Open[start_pos];
   rate.low=Low[start_pos];
   rate.high=High[start_pos];
   rate.tick_volume=(long)Volume[start_pos];
   rate.spread=0;
   rate.real_volume=0;
   //--- normalize open time
//   rate.time=Time[start_pos]/periodseconds;
//   rate.time*=periodseconds;
   next_bar_time=SetBarTime(rate.time,Time[start_pos],periodseconds);
   for(i=start_pos-1; i>=0; i--)
     {
      if(IsStopped())
         break;
      time0=Time[i];
/*
      //--- history may be updated
      if(i==0)
        {
         //--- modify index if history was updated
         if(RefreshRates())
            i=iBarShift(NULL,0,time0);
        }
*/
      //---
//      if(time0>=rate.time+periodseconds || i==0)
      if(time0>=next_bar_time || i==0)
        {
//         if(i==0 && time0<rate.time+periodseconds)
         if(i==0 && time0<next_bar_time)
           {
            rate.tick_volume+=(long)Volume[0];
            if(rate.low>Low[0])
               rate.low=Low[0];
            if(rate.high<High[0])
               rate.high=High[0];
            rate.close=Close[0];
           }
         last_fpos=FileTell(ExtHandle);
         last_volume=(long)Volume[i];
         FileWriteStruct(ExtHandle,rate);
         cnt++;
//         if(time0>=rate.time+periodseconds)
         if(time0>=next_bar_time)
           {
//            rate.time=time0/periodseconds;
//            rate.time*=periodseconds;
            next_bar_time=SetBarTime(rate.time,time0,periodseconds);
            rate.open=Open[i];
            rate.low=Low[i];
            rate.high=High[i];
            rate.close=Close[i];
            rate.tick_volume=last_volume;
            if(i==0)
              {
               FileWriteStruct(ExtHandle,rate);
               cnt++;
              }
           }
        }
       else
        {
         rate.tick_volume+=(long)Volume[i];
         if(rate.low>Low[i])
            rate.low=Low[i];
         if(rate.high<High[i])
            rate.high=High[i];
         rate.close=Close[i];
        }
     }
   FileFlush(ExtHandle);
   PrintFormat("%d record(s) written",cnt);
/*
//--- collect incoming ticks
   datetime last_time=LocalTime()-5;
   long     chart_id=0;
//---
   while(!IsStopped())
     {
      datetime cur_time=LocalTime();
      //--- check for new rates
      if(RefreshRates())
        {
         time0=Time[0];
         FileSeek(ExtHandle,last_fpos,SEEK_SET);
         //--- is there current bar?
         if(time0<rate.time+periodseconds)
           {
            rate.tick_volume+=(long)Volume[0]-last_volume;
            last_volume=(long)Volume[0];
            if(rate.low>Low[0])
               rate.low=Low[0];
            if(rate.high<High[0])
               rate.high=High[0];
            rate.close=Close[0];
           }
         else
           {
            //--- no, there is new bar
            rate.tick_volume+=(long)Volume[1]-last_volume;
            if(rate.low>Low[1])
               rate.low=Low[1];
            if(rate.high<High[1])
               rate.high=High[1];
            //--- write previous bar remains
            FileWriteStruct(ExtHandle,rate);
            last_fpos=FileTell(ExtHandle);
            //----
            rate.time=time0/periodseconds;
            rate.time*=periodseconds;
            rate.open=Open[0];
            rate.low=Low[0];
            rate.high=High[0];
            rate.close=Close[0];
            rate.tick_volume=(long)Volume[0];
            last_volume=rate.tick_volume;
           }
         //----
         FileWriteStruct(ExtHandle,rate);
         FileFlush(ExtHandle);
         //--- target chart is not found yet. it can be opened via Main menu - File - Open offline
         if(chart_id==0)
           {
            long id=ChartFirst();
            while(id>=0)
              {
               //--- find appropriate offline chart
               if(ChartSymbol(id)==Symbol() && ChartPeriod(id)==i_period && ChartGetInteger(id,CHART_IS_OFFLINE))
                 {
                  chart_id=id;
                  ChartSetInteger(chart_id,CHART_AUTOSCROLL,true);
                  ChartSetInteger(chart_id,CHART_SHIFT,true);
                  ChartNavigate(chart_id,CHART_END);
                  ChartRedraw(chart_id);
                  PrintFormat("Chart window [%s,%d] found",Symbol(),i_period);
                  break;
                 }
               //--- enumerate opened charts
               id=ChartNext(id);
              }
           }
         //--- refresh window not frequently than 1 time in 2 seconds
         if(chart_id!=0 && cur_time-last_time>=2)
           {
            ChartSetSymbolPeriod(chart_id,Symbol(),i_period);
            last_time=cur_time;
           }
        }
      Sleep(50);
     }      
*/
//---
   if(ExtHandle>=0)
     {
      FileClose(ExtHandle);
      ExtHandle=-1;
      cnt=0;
     }
   Comment(i_period,"min. fin!");
   }
//---
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   if(ExtHandle>=0)
     {
      FileClose(ExtHandle);
      ExtHandle=-1;
     }
//---
  }
//+------------------------------------------------------------------+
//| バーの開始時間を計算する ※戻り値は次のバー開始時間              |
//+------------------------------------------------------------------+
datetime SetBarTime(datetime &bar_time,datetime current_time,int periodseconds)
  {
   datetime next_bar_time;
   MqlDateTime mql_date_time;
   switch(periodseconds)
     {
      case 604800:   // Weekly
         bar_time=current_time-current_time%86400; // Daily
         bar_time=bar_time-TimeDayOfWeek(bar_time)*86400;
         next_bar_time=bar_time+periodseconds;
         break;
      case 2592000:  // Monthly
         bar_time=current_time-current_time%86400; // Daily
         bar_time=bar_time-(TimeDay(bar_time)-1)*86400;
         TimeToStruct(bar_time,mql_date_time);
         if(mql_date_time.mon!=12)
            mql_date_time.mon++;
         else
           {
            mql_date_time.year++;
            mql_date_time.mon=1;
           }
         next_bar_time=StructToTime(mql_date_time);
         break;
      default:
         bar_time=current_time-current_time%periodseconds;
         next_bar_time=bar_time+periodseconds;
         break;
     }
   return(next_bar_time);
  }
//+------------------------------------------------------------------+

 
テキストをコピペして.mq4ファイルで保存し、MT4でコンパイルして下さい。
PeriodConverterの著作権はMetaQuotes社にあるので、コンパイル済ファイルの配布は行いません。
まぁ、MQL5ライブラリに登録する程度なら問題無いかもしれませんが…
 
PeriodConverterAllExの実行結果は下図のとおりです。
period_converter_all_ex_weekly_monthly.png
 
5分足と15分足の最終足、週足と月足とも正しく生成されています。
 
最後にWinMergeでのソースコード比較結果を添付します。ご参考まで。
PeriodConverterからAllExへの変更箇所
 

テーマ : FX(外国為替証拠金取引)
ジャンル : 株式・投資・マネー

案外知られていない、MT4添付スクリプト「PeriodConverter」のバグ(正しくは制約)

MT4に添付されているスクリプト「PeriodConverter」は、主に1分足から上位時間足を作成するために使われています。
このスクリプトはパラメータ「Period multiplier factor」の設定を必要としますが、この設定を省き、5分足~月足まで一度に生成する「Period_ConverterALL」や「all_period_converter」などの派生スクリプトも多数公開されています。
 
しかし、これら「PeriodConverter」と派生スクリプトにバグ(正しくは制約)があることは、案外知られていません。
 
それにはまず、MT4添付スクリプト「PeriodConverter」の目的を理解する必要があります。
 
「PeriodConverter」の本来の目的は、オンラインのチャートに常駐させて、パラメータで指定した倍率の上位時間足をリアルタイムで生成していくものです。
ですので、オフラインチャートの5分足~月足を生成して終わり、という使い方は、スクリプトの本来の目的から外れています
 
この弊害がどこに現れるかというと、最新時間足の生成が行われない問題と、週足・月足のOpen時間が正しく設定されない問題が発生します。
 
「PeriodConverter」や派生スクリプトで、オフラインチャート1分足から上位時間足を生成した場合、下図のようになります。
period_converter_weekly_monthly_bug.png
 
どこが間違っているか分かりますか?
 
まず、1分足の終了が23時45分ですので、5分足と15分足の23時45分にも足が生成されているべきですが、生成されていません。
 
次に、週足の差出人(開始日時)が2005年1月6日になっていますが、この日は木曜日です。 
週足は日曜日から始まりますので、本来の週足は2005年1月9日(日)から始まります。
月足も同様で、本来は2005年1月1日から始まります。
 
よって、下図が正しいバー生成結果となります。
period_converter_weekly_monthly_fixed.png
(ForexStudioのDatacenterを使って出力したヒストリカルデータ)
 
MTF系のインジケーターやEAでは、週足を参照しているケースもあります。
MTF系ロジックのバックテストを行う際、PeriodConverterや派生スクリプトで生成したヒストリカルデータでは、正しい週足が生成されていないことを認識しておきましょう。
 

テーマ : FX(外国為替証拠金取引)
ジャンル : 株式・投資・マネー

UTC+0のヒストリカルデータを、UTC+2/+3や日本時間(UTC+9)にするVBスクリプト

前回の記事でJForexを使ってDukascopyのヒストリカルデータをダウンロードしましたが、時間はUTC+0固定になっています。
これをUTC+2夏時間有(UTC+2/+3)や、日本時間(UTC+9)に変換するVBスクリプトを作成しました。 
 
UTC+0のhstファイルをUTC+2夏時間有に変換.vbs
Option Explicit

'----------------------------------------------------------------------------
' UTC+0のヒストリカルデータ(.hst)を、UTC+2夏時間有に変換するVBScript
' スクリプトファイルに.hstファイルをドラッグアンドドロップして使用する
' 出力先はスクリプト実行フォルダに作成される work フォルダの中
'
' ※作成された.hstで上書きする前にオリジナルの.hstをバックアップしましょう。
'----------------------------------------------------------------------------

Const adTypeBinary = 1
Const adTypeText = 2
Const adSaveCreateOverWrite = 2
Const adReadAll = -1

Dim lngDatetime, binDatetime    ' bar start timeの整数値とバイナリ配列
Dim dteDatetime                 ' bar start timeの日付型変換後
Dim workFolder, workFile        ' 出力フォルダ、出力ファイル
Dim objFs                       ' ファイル操作(FileSystemObject)
Dim objStBin, objStIn, objStOut ' バイナリ操作(ADODB.Stream)
Dim lngStPos                    ' ファイル操作位置
Dim intVersion                  ' Version番号
Dim intBarsStructSize           ' Bars構造体のサイズ
Dim intStructPosition           ' 構造体のデータ位置
Dim i

' 引数が無いなら終了
If WScript.Arguments.Count < 1 Then WScript.Quit

Set objFs = CreateObject("Scripting.FileSystemObject")
Set objStBin = CreateObject("ADODB.Stream")
Set objStIn = CreateObject("ADODB.Stream")
Set objStOut = CreateObject("ADODB.Stream")

' 出力フォルダ作成
workFolder = objFs.BuildPath(objFs.GetFile(WScript.ScriptFullName).ParentFolder.Path, "work")
If Not objFs.FolderExists(workFolder) Then objFs.CreateFolder (workFolder)

' hstファイル書き換え
For i = 0 To WScript.Arguments.Count - 1
  If Right(WScript.Arguments(i), 4) = ".hst" Then
    If objFs.FileExists(WScript.Arguments(i)) Then
      
      ' .hstファイルを開く
      objStIn.Type = adTypeBinary
      objStIn.Open
      objStIn.LoadFromFile WScript.Arguments(i)
      
      ' 出力側のストリームを開く
      objStOut.Type = adTypeBinary
      objStOut.Open
      
      ' 出力ファイル名を指定
      workFile = objFs.GetFileName(WScript.Arguments(i))
      workFile = objFs.BuildPath(workFolder, workFile)
      
      ' 出力側ストリームへコピー
      objStIn.Position = 0
      objStOut.Write objStIn.Read(adReadAll)
      
      ' バージョン取得(400 or 401)
      objStIn.Position = 0
      intVersion = CLng("&H" & Hex(AscW(objStIn.Read(2))))
      If intVersion = 400 Then
          intBarsStructSize = 44  ' 構造体サイズ
          intStructPosition = 0   ' 書込位置
      Else
          intBarsStructSize = 60  ' 構造体サイズ
          intStructPosition = 0   ' 書込位置
      End If
      
      ' バー配列のbar start timeを書き換える
      ' ※ヘッダー部148bytes、バー構造体は44 or 60bytes
      For lngStPos = (148 + intStructPosition) To objStIn.Size - 1 Step intBarsStructSize
        
        ' 時間の読み取り
        objStIn.Position = lngStPos
        lngDatetime = CLng("&H" & Hex(AscW(objStIn.Read(2))))
        lngDatetime = lngDatetime + CLng("&H" & Hex(AscW(objStIn.Read(2)))) * &H10000
        dteDatetime = 25569 + lngDatetime / 86400
        
        ' アメリカ東部夏時間(EDT)の期間は1時間進める (UTC+0/+0 → UTC+0/+1)
        If Year(dteDatetime) >= 2007 Then
          If dteDatetime >= DateSerial(Year(dteDatetime), 3, 14 - (Weekday(DateSerial(Year(dteDatetime), 3, 1)) + 5) Mod 7) Then
            If dteDatetime < DateSerial(Year(dteDatetime), 11, 7 - (Weekday(DateSerial(Year(dteDatetime), 11, 1)) + 5) Mod 7) Then
              dteDatetime = dteDatetime + TimeSerial(1, 0, 0)
            End If
          End If
        Else
          If dteDatetime >= DateSerial(Year(dteDatetime), 4, 7 - (Weekday(DateSerial(Year(dteDatetime), 4, 1)) + 5) Mod 7) Then
            If dteDatetime < DateSerial(Year(dteDatetime), 11, 0 - (Weekday(DateSerial(Year(dteDatetime), 11, 1)) + 5) Mod 7) Then
              dteDatetime = dteDatetime + TimeSerial(1, 0, 0)
            End If
          End If
        End If
        
        ' さらに2時間進める (UTC+0/+1 → UTC+2/+3)
        dteDatetime = dteDatetime + TimeSerial(2, 0, 0)
        lngDatetime = CLng((dteDatetime - 25569) * 86400)
        
        ' 時間のバイナリ配列作成
        objStBin.Type = adTypeText
        objStBin.Charset = "unicode"
        objStBin.Open
        objStBin.WriteText ChrW(lngDatetime Mod &H10000)
        objStBin.WriteText ChrW(lngDatetime \ &H10000)
        objStBin.Position = 0
        objStBin.Type = adTypeBinary
        objStBin.Position = 2               ' 先頭2bytesはBOMなので読まない
        binDatetime = objStBin.Read(4)
        objStBin.Close
        
        ' 時間を更新
        objStOut.Position = lngStPos
        objStOut.Write binDatetime
        
      Next
      
      ' 出力ファイル保存
      objStOut.SaveToFile workFile, adSaveCreateOverWrite
      objStOut.Close
      objStIn.Close
      
    End If
  End If
Next

Set objStBin = Nothing
Set objStOut = Nothing
Set objStIn = Nothing
Set objFs = Nothing

MsgBox "出力しました。workフォルダを確認して下さい", vbInformation

 
UTC+0のhstファイルを日本時間に変換.vbs
Option Explicit

'----------------------------------------------------------------------------
' UTC+0のヒストリカルデータ(.hst)を、日本時間(UTC+9)に変換するVBScript
' スクリプトファイルに.hstファイルをドラッグアンドドロップして使用する
' 出力先はスクリプト実行フォルダに作成される work フォルダの中
'
' ※作成された.hstで上書きする前にオリジナルの.hstをバックアップしましょう。
'----------------------------------------------------------------------------

Const adTypeBinary = 1
Const adTypeText = 2
Const adSaveCreateOverWrite = 2
Const adReadAll = -1

Dim lngDatetime, binDatetime    ' bar start timeの整数値とバイナリ配列
Dim dteDatetime                 ' bar start timeの日付型変換後
Dim workFolder, workFile        ' 出力フォルダ、出力ファイル
Dim objFs                       ' ファイル操作(FileSystemObject)
Dim objStBin, objStIn, objStOut ' バイナリ操作(ADODB.Stream)
Dim lngStPos                    ' ファイル操作位置
Dim intVersion                  ' Version番号
Dim intBarsStructSize           ' Bars構造体のサイズ
Dim intStructPosition           ' 構造体のデータ位置
Dim i

' 引数が無いなら終了
If WScript.Arguments.Count < 1 Then WScript.Quit

Set objFs = CreateObject("Scripting.FileSystemObject")
Set objStBin = CreateObject("ADODB.Stream")
Set objStIn = CreateObject("ADODB.Stream")
Set objStOut = CreateObject("ADODB.Stream")

' 出力フォルダ作成
workFolder = objFs.BuildPath(objFs.GetFile(WScript.ScriptFullName).ParentFolder.Path, "work")
If Not objFs.FolderExists(workFolder) Then objFs.CreateFolder (workFolder)

' hstファイル書き換え
For i = 0 To WScript.Arguments.Count - 1
  If Right(WScript.Arguments(i), 4) = ".hst" Then
    If objFs.FileExists(WScript.Arguments(i)) Then
      
      ' .hstファイルを開く
      objStIn.Type = adTypeBinary
      objStIn.Open
      objStIn.LoadFromFile WScript.Arguments(i)
      
      ' 出力側のストリームを開く
      objStOut.Type = adTypeBinary
      objStOut.Open
      
      ' 出力ファイル名を指定
      workFile = objFs.GetFileName(WScript.Arguments(i))
      workFile = objFs.BuildPath(workFolder, workFile)
      
      ' 出力側ストリームへコピー
      objStIn.Position = 0
      objStOut.Write objStIn.Read(adReadAll)
      
      ' バージョン取得(400 or 401)
      objStIn.Position = 0
      intVersion = CLng("&H" & Hex(AscW(objStIn.Read(2))))
      If intVersion = 400 Then
          intBarsStructSize = 44  ' 構造体サイズ
          intStructPosition = 0   ' 書込位置
      Else
          intBarsStructSize = 60  ' 構造体サイズ
          intStructPosition = 0   ' 書込位置
      End If
      
      ' バー配列のbar start timeを書き換える
      ' ※ヘッダー部148bytes、バー構造体は44 or 60bytes
      For lngStPos = (148 + intStructPosition) To objStIn.Size - 1 Step intBarsStructSize
        
        ' 時間の読み取り
        objStIn.Position = lngStPos
        lngDatetime = CLng("&H" & Hex(AscW(objStIn.Read(2))))
        lngDatetime = lngDatetime + CLng("&H" & Hex(AscW(objStIn.Read(2)))) * &H10000
        dteDatetime = 25569 + lngDatetime / 86400
        
        ' 9時間進める (UTC+0 → UTC+9)
        dteDatetime = dteDatetime + TimeSerial(9, 0, 0)
        lngDatetime = CLng((dteDatetime - 25569) * 86400)
        
        ' 時間のバイナリ配列作成
        objStBin.Type = adTypeText
        objStBin.Charset = "unicode"
        objStBin.Open
        objStBin.WriteText ChrW(lngDatetime Mod &H10000)
        objStBin.WriteText ChrW(lngDatetime \ &H10000)
        objStBin.Position = 0
        objStBin.Type = adTypeBinary
        objStBin.Position = 2               ' 先頭2bytesはBOMなので読まない
        binDatetime = objStBin.Read(4)
        objStBin.Close
        
        ' 時間を更新
        objStOut.Position = lngStPos
        objStOut.Write binDatetime
        
      Next
      
      ' 出力ファイル保存
      objStOut.SaveToFile workFile, adSaveCreateOverWrite
      objStOut.Close
      objStIn.Close
      
    End If
  End If
Next

Set objStBin = Nothing
Set objStOut = Nothing
Set objStIn = Nothing
Set objFs = Nothing

MsgBox "出力しました。workフォルダを確認して下さい", vbInformation

 
テキストをコピペし、ファイル拡張子.vbsとして保存して下さい。
使い方はスクリプトのコメントに記載したとおりです。
.hstファイル(複数可)を.vbsファイルへドラッグ&ドロップ後、暫く待つと処理終了のダイアログが表示されますので、workフォルダに作成された.hstファイルを元の.hstファイルと差し替えて下さい。
 
なおスクリプトで修正可能な時間足は、1分足~1時間足までです。
それ以上の長時間足では正しく修正できません。
長時間足は、Period ConverterなどのMT4スクリプトで作成し直して下さい。
 
ちなみに、2003年~2016年の1分足ヒストリカルデータを変換する場合、1ファイルあたり数分掛かります。
 

テーマ : FX(外国為替証拠金取引)
ジャンル : 株式・投資・マネー

【Dukascopy】JForexから1分足のヒストリカルデータをダウンロードする

Dukascopyのヒストリカルデータを使う方法として、Tickstoryが有名です。
ただ、モデリング品質が恣意的に99%に書換えられている事や、Tickレベルの過剰最適化(カーブフィッティング)を招いて他の業者での成績が伴わないケースがある等、必ずしも良い面ばかりではありません。
 
本質的な事を言ってしまえば、MT4の擬似Tickで崩れてしまうようなEAでは、実運用に於いて安定した成績を残すことは期待できません。
 
これらの理由で最小時間は1分足で構わない!と割りきった場合、Tickstoryのダウンロード画面は多機能すぎて煩雑に感じてしまいます。
 
 
そこで、Dukascopyの1分足ヒストリカルデータを、簡単にダウンロードする方法を紹介します。
 
1.デューカスコピージャパンのデモ口座を開設します。
https://www.dukascopy.jp/japan/japanese/home/
 
2.ログイン画面から、「デモ版JForex」をクリックします。
https://www.dukascopy.jp/japan/japanese/forex/trading-login/
jforex_download.png
※予めJavaランタイムをインストールしておいて下さい。
※Chrome、FireFox、Edgeの場合、ダウンロードされたdukascopy-jp.jnlpを実行すればOKです。
 
3.デモ口座にログインします。
jforex_demo_login.png
 
4.[ツール]-[ヒストリカルデータ管理]をクリックします。
jforex_historical_data_center.png
 
5.右下にヒストリカルデータ管理のタブが追加されます。
このまま操作しても良いのですが、別窓で開くことも出来ます。
jforex_historical_data_center_2.png
 
6.ダウンロードする期間とファイル形式、通貨ペアを選択します。
自分はFXDDヒストリカルデータと同じインポート手順を踏むために、HST形式でダウンロードしています。詳細は下図参照して下さい。
jforex_historical_data_center_3.png
 
7.ダウンロードを開始します。
初回ダウンロード時は免責事項が表示されますので、承認してください。
全通貨ペア、全期間データのダウンロードには数時間掛かります。(7GB超)
jforex_historical_data_center_4.png

8.JForexからHST形式でダウンロードした場合、下図のように保存されます。
ファイル名を見ればデータ取得期間が分かるので便利です。
jforex_historical_data_center_5.png
 
9.ダウンロードしたhstファイルを、MT4にインポートします。
ここから先は、FXDDヒストリカルデータのインポートと同様のため、説明は割愛します。
 
 
ただし、ヒストリカルデータの時間がUTC+0なので、UTC+2/+3に変換したいと思うことがあるかもしれません。
この変換をするVBスクリプトを、後日掲載しようと思います。
 
なお、日本時間(UTC+9)にする場合は、MT4のインポート時に表示移動の時間を設定するだけでOKです、、、と書きたかったのですが、hstファイルのインポート時には設定出来なかった orz...
UTC+0 → UTC+9 のVBスクリプトも考えておきます。
 
デューカスコピー・ジャパン 口座開設
 

テーマ : FX(外国為替証拠金取引)
ジャンル : 株式・投資・マネー

プロフィール

nekonote

Author:nekonote

EAを作るのが趣味になってしまったらしい。

あとマニアックな運用とかetc...その時の気分で書き殴る(?)
そんなブログ

※当ブログ記事へのリンクはご自由にどうぞ

 
運用は…fx-onのみんなのMT4に公開しているかも?
fx-on 通常会員ページ
fx-on 出品者ページ

最新記事
最新コメント
月別アーカイブ
カテゴリ
検索フォーム
ブログランキング
にほんブログ村 為替ブログ システムトレード 自作EA派へ





QRコード
QR
RSSリンクの表示
リンク
FX情報サイト
 優秀トレーダーの投資法をゲット!
FX投資情報コミュニティfx-on.com


国内MT4取扱会社
外為ファイネスト カコテン iOsMA (type DI) EURAUD タイアップキャンペーン

アヴァトレード・ジャパン株式会社 カコテン iOsMA (type DI) EURAUD タイアップキャンペーン

FOREX.com×タイアップキャンペーン☆Beatrice-07 FXTF×ForexSolidタイアップキャンペーン



自作EA紹介


EAフォワード集計結果
海外MT4業者
海外業者を選ぶ際は、まず金融庁の「注意喚起」を熟読して下さい。無登録業者で事故っても自己責任ですよ!
自分はゲムトレード&GEMFOREXに突撃してみましたw




自分もカコテンシリーズを幾つか出品しています。 運用結果でネタが集まれば時々記事にします。

ゲムトレードはEAの将来価値をリスクヘッジするには良い仕組みを提供していると思います。ただし本当に実力のあるEAはfx-on等から買った方が良いでしょう。
取引明細には現れませんがIBのような仕組みでゲムトレードへ報酬が渡っていますので、単一EAの長期運用ではデメリットが成績に現れると思われます。

※繰り返しますが海外業者でトラブっても自己責任です。お忘れなく!
FX専用VPS
レンタルサーバーなら使えるねっと



みんなのMT4
紫色:リアル口座
水色:デモ口座
ねこぱんち | fx-on.com
ねこぱんちMAXでも | fx-on.com
ねこのまえあし | fx-on.com
€$ XM demo | fx-on.com
£$ FxPro demo | fx-on.com
€¥ IFC Markets demo 2nd! | fx-on.com
£¥ IC Markets demo  | fx-on.com
$¥ MGK Global demo | fx-on.com
BigBoss demo AUDJPY | fx-on.com
€x LandFX demo | fx-on.com
KAKO10 iIchimoku リアル OANDA | fx-on.com
KAKO10 iIchimoku デモ FXTF | fx-on.com
KAKO10_iMA(H27.5~) | fx-on.com
KAKO10 iMA デモ Axiory(運用終了) | fx-on.com
KAKO10 iMA デモ Axiory新鯖 | fx-on.com
Ava demo iOsMA方向性スイング(運用終了) | fx-on.com
カコテン iOsMA (type DI) デモ Centrade | fx-on.com
カコテン iMomentum (type DI) デモ Arena | fx-on.com
瞬殺!!! NCSEC demo ※運用終了 | fx-on.com
GEMFOREX demo 新サーバーお試し ※破綻 | fx-on.com
 | fx-on.com
 | fx-on.com
 | fx-on.com
 | fx-on.com