So-net無料ブログ作成

hstファイルをcsvに変換 [C++]

別にFXをやっている訳ではないんですが、いやちょっとはやってみたいとも思いますけど、そもそも元手が(10万とか)ないんで無理なのが悲しいところ。でもちょっと世界をのぞいてみたいと思いまして、為替相場の動きを観察しようと思います。

そのためにはまず過去のデータが必要です。2005年から1分ごとのデータが、FXDD という証券会社のメタトレーダーのヒストリカルデータというところからダウンロードできました。

さて、このデータ。メタトレーダー4というFX取引用のアプリのフォーマットのようです。
フォーマットの中身はMT4を使ってFXに解説されていました。

探せばごろごろあるのでしょうが、向学のために csv に変換するプログラムを書いてみました。本当は C# でサクッと行きたかったのですが、諸事情により VisualStudio をインストールしていないので、 xcode で c++ で書きました。

ソースコードは GitHub からダウンロードできます。

#include 
#include 
#include 
#include 

using namespace std;

typedef struct _HistoryHeader
{
    uint32_t    version;
    char        copyright[64];
    char        symbol[12];
    int32_t     period;
    int32_t     digits;
    uint32_t    timesign;
    uint32_t    last_sync;
    uint32_t    reserved[13];
} HistoryHeader;

#pragma pack(push,1)
typedef struct _RateInfo
{
    uint32_t    ctm;
    double      open;
    double      low;
    double      high;
    double      close;
    double      vol;
} RateInfo;
#pragma pack(pop)


void printHistoryHeader(const HistoryHeader& header)
{
    cout << "version   : " << header.version << endl;
    cout << "copyright : " << header.copyright << endl;
    cout << "symbol    : " << header.symbol << endl;
    cout << "period    : " << header.period << endl;
    cout << "digits    : " << header.period << endl;
    time_t tmp = header.timesign;
    cout << "timesign  : " << put_time(localtime(&tmp), "%F %T") << endl;
    tmp = header.last_sync;
    cout << "last_sync : " << put_time(localtime(&tmp), "%F %T") << endl;
}

void printRate(const RateInfo& rate, ostream& ost)
{
    time_t tmp = rate.ctm;
    ost << put_time(std::localtime(&tmp), "%F %T");
    ost << "," << rate.open;
    ost << "," << rate.low;
    ost << "," << rate.high;
    ost << "," << rate.close;
    ost << "," << rate.vol << endl;
}

int main(int argc, const char * argv[])
{
    if(argc < 2) {
        cout << "need to give hst file and output file" << endl;
        cout << "ex) hstconverter [hst file] [output file]" << endl;
        return 1;
    }
    
    ifstream ifs;
    ifs.open(argv[1], ios::in | ios::binary);
    if(!ifs) {
        cout << "file open error" << endl;
        return 1;
    }
    
    HistoryHeader header;
    ifs.read((char*)&header, sizeof(header));
    if(ifs.bad()) {
        cout << "file read error" << endl;
        return 1;
    }
    
    printHistoryHeader(header);
    
    ofstream ofs;
    ofs.open(argv[2], ios::out | ios::trunc);
    if(!ofs.is_open()) {
        cout << "failed to create a file : " << argv[2] << endl;
        return 1;
    }
    
    RateInfo rate;
    while(!ifs.eof()) {
        ifs.read((char*)&rate, 44);
        if(ifs.bad()) {
            cout << "file read error" << endl;
            return 1;
        }
        printRate(rate, ofs);
    }
    
    cout << "done" << endl;
    
    return 0;
}


#pragma pack でバイトアラインを無効にして、構造体に一気にデータを読み込んでいます。
これってバイトオーダーが違う処理系だったら大丈夫なのでしょうか。

そしてフォーマットにある time_t はなんと 32bit time_t のことの様なので、
uint32_t に置き換えて構造体に取り込んで、使うときに time_t にキャストしています。

次のように実行して USDJPY.hst を csv に変換して output.csv に書き出します。
hstconverter USDJPY.hst output.csv


できたファイルの内容はこんな感じ。
2005-01-10 11:31:00,104.79,104.79,104.79,104.79,5
2005-01-10 11:32:00,104.79,104.78,104.79,104.78,6
2005-01-10 11:33:00,104.78,104.77,104.78,104.77,5
...
2014-08-09 07:59:00,102.063,102.06,102.067,102.064,34
2014-08-09 07:59:00,102.063,102.06,102.067,102.064,34


さてこれを使ってどうするか。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。