import os
import numpy as np
import pandas as pd
workdir = 'R:/WORK/'
def df_to_hst(outfilepath, df, symbol=None, period=None, digits=None, timesign=0, last_sync=0):
"""df to mt4 .hst"""
# df は datetimeindexで、Open High Low Close Volume というカラム名で値を持っているものを想定
# outfilepath はファイル名まで含めたパスを指定する
# symbol, period の引数が省略されている場合、USDJPY60.hst のようなファイル名なら
# USDJPY, 60 をパースしてそれをヘッダ情報として使う
# 引数で指定があればそっちをヘッダ情報として使う
# 特殊なシンボル名や数値を含むシンボル名の場合はそれぞれ引数を指定したほうが確実
# digits は指定が無い場合、シンボル名にJPYが含まれていればdigitsは 3、そうでないなら5にする
# これも引数で指定があればその値をヘッダ情報に使う
import re
if symbol is None:
symbol = re.search('[A-Z]+', os.path.split(outfilepath)[-1]).group()
if period is None:
period = re.search('[0-9]+', os.path.split(outfilepath)[-1]).group()
if digits is None:
digits = 3 if 'JPY' in symbol else 5
if symbol is None or period is None or digits is None:
print('ヘッダに書き出す情報が足りないので中止!')
return
dtype = [('version','i4'), ('copyright','S64'), ('symbol','S12'), ('period','i4'),
('digits','i4'), ('timesign','i4'), ('last_sync','i4'), ('unused','S52')]
header = np.empty(1, dtype=dtype)
header['version'] = 401
header['copyright'] = '(C)opyright 2003, MetaQuotes Software Corp.'
header['symbol'] = symbol
header['period'] = period
header['digits'] = digits
header['timesign'] = timesign
header['last_sync'] = last_sync
header['unused'] = ''
dtype = [('Time','u8'), ('Open','f8'), ('High','f8'), ('Low','f8'),
('Close','f8'), ('Volume','i8'), ('s','i4'), ('r','i8')]
data = np.zeros(len(df), dtype=dtype)
data['Time'] = df.index.astype(np.int64)//10**9
for c in ['Open', 'High', 'Low', 'Close', 'Volume']:
data[c] = df[c]
with open(outfilepath, 'wb') as f:
f.write(header.tobytes()+data.tobytes())
'testdata.hst'の中身はMT4からコピーしてきたUSDJPY60.hst
USDJPY60.hstは出力するファイル名で使いたいので読み込む前に名前を変えた
def read_hst(path):
with open(path, 'rb') as f:
dtype = [('version','i4'), ('copyright','S64'), ('symbol','S12'), ('period','i4'),
('digits','i4'), ('timesign','i4'), ('last_sync','i4'), ('unused','S52')]
header = np.frombuffer(f.read(148), dtype=dtype)
print(header[0])
dtype = [('Time','u8'), ('Open','f8'), ('High','f8'), ('Low','f8'),
('Close','f8'), ('Volume','i8'), ('s','i4'), ('r','i8')]
df = pd.DataFrame(np.frombuffer(f.read(), dtype=dtype).astype(dtype[:-2]))
dt = df['Time']
df = df.set_index(pd.to_datetime(df['Time'], unit='s')).drop('Time', axis=1)
return df
src_df = read_hst(os.path.join(workdir, 'testdata.hst'))
print('shape', src_df.shape)
df_to_hst(os.path.join(workdir, 'USDJPY60.hst'), src_df)
df = read_hst(os.path.join(workdir, 'USDJPY60.hst'))
# 一応値が違うところが無いか確認
(src_df != df).sum()
btc = pd.read_csv(os.path.join(workdir, '.coincheckJPY.csv'), names=['Time', 'Price', 'Volume'])
btc['Time'] = pd.to_datetime(btc['Time'], unit='s')
btc.set_index('Time', inplace=True)
print('data len', len(btc))
btc.tail()
for tf in [1, 5, 15, 30, 60, 240, 1440]:
btc_ohlcv = btc['Price'].resample('{}T'.format(tf)).ohlc().dropna()
btc_ohlcv.columns = ['Open', 'High', 'Low', 'Close']
btc_ohlcv['Volume'] = btc['Volume'].resample('1T').sum().dropna()
btc_ohlcv['Volume'] /= 0.00000001 # .hstのVolumeはlong型なのでSatoshiにする
hstpath = os.path.join(workdir, 'BTCJPY{}.hst'.format(tf))
df_to_hst(hstpath, btc_ohlcv, symbol='BTCJPY', period=tf, digits=0)
日足などを作るとき任意の時間を区切りにしたいときは
resample('24H', base=6) のようにすればOK(´・ω・`)
for tf in [1, 5, 15, 30, 60, 240, 1440]:
print('shape', read_hst(os.path.join(workdir, 'BTCJPY{}.hst'.format(tf))).shape)