|
|
|
@ -8,7 +8,9 @@ import json |
|
|
|
import csv |
|
|
|
import csv |
|
|
|
import datetime |
|
|
|
import datetime |
|
|
|
import struct |
|
|
|
import struct |
|
|
|
|
|
|
|
import re |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from pytz import timezone |
|
|
|
|
|
|
|
|
|
|
|
def sec_from_period(period): |
|
|
|
def sec_from_period(period): |
|
|
|
if period == "M1": |
|
|
|
if period == "M1": |
|
|
|
@ -24,21 +26,35 @@ def sec_from_period(period): |
|
|
|
elif period == "D": |
|
|
|
elif period == "D": |
|
|
|
return 86400 |
|
|
|
return 86400 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_month_code(month): |
|
|
|
|
|
|
|
if month < 1 or month > 12: |
|
|
|
|
|
|
|
return None |
|
|
|
|
|
|
|
codes = ['F', 'G', 'H', 'J', 'K', 'M', 'N', 'Q', 'U', 'V', 'X', 'Z'] |
|
|
|
|
|
|
|
return codes[month - 1] |
|
|
|
|
|
|
|
|
|
|
|
def main(): |
|
|
|
def main(): |
|
|
|
parser = argparse.ArgumentParser(description='Finam quote downloader') |
|
|
|
parser = argparse.ArgumentParser(description='Finam quote downloader') |
|
|
|
parser.add_argument('-i', '--input-file', action='store', dest='input_file', help='Input filename', required=True) |
|
|
|
parser.add_argument('-i', '--input-file', action='store', dest='input_file', help='Input filename', required=True) |
|
|
|
parser.add_argument('-p', '--timeframe', action='store', dest='timeframe', help='Data timeframe', required=True) |
|
|
|
parser.add_argument('-p', '--timeframe', action='store', dest='timeframe', help='Data timeframe', required=True) |
|
|
|
parser.add_argument('-o', '--hap', action='store', dest='hap', help='HAP endpoint', required=True) |
|
|
|
parser.add_argument('-o', '--hap', action='store', dest='hap', help='HAP endpoint', required=True) |
|
|
|
parser.add_argument('-y', '--hap-symbol', action='store', dest='hap_symbol', help='HAP symbol', required=True) |
|
|
|
parser.add_argument('-y', '--hap-symbol', action='store', dest='hap_symbol', help='HAP symbol', required=True) |
|
|
|
parser.add_argument('-d', '--time-delta', action='store', dest='time_delta', help='Time delta (hours)') |
|
|
|
parser.add_argument('-d', '--time-delta', action='store', dest='time_delta', help='Time delta (seconds)') |
|
|
|
parser.add_argument('-f', '--force-from', action='store', dest='force_from', help='Force period start') |
|
|
|
parser.add_argument('-f', '--force-from', action='store', dest='force_from', help='Force period start') |
|
|
|
parser.add_argument('-t', '--force-to', action='store', dest='force_to', help='Force period end') |
|
|
|
parser.add_argument('-t', '--force-to', action='store', dest='force_to', help='Force period end') |
|
|
|
|
|
|
|
parser.add_argument('-z', '--timezone', action='store', dest='timezone', help='Timestamps timezone') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
args = parser.parse_args() |
|
|
|
args = parser.parse_args() |
|
|
|
|
|
|
|
|
|
|
|
period = args.timeframe |
|
|
|
period = args.timeframe |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
utc_tz = timezone('UTC') |
|
|
|
|
|
|
|
if args.timezone is None: |
|
|
|
|
|
|
|
tz = utc_tz |
|
|
|
|
|
|
|
else: |
|
|
|
|
|
|
|
tz = timezone(args.timezone) |
|
|
|
|
|
|
|
|
|
|
|
out_symbol = args.hap_symbol |
|
|
|
out_symbol = args.hap_symbol |
|
|
|
|
|
|
|
|
|
|
|
ctx = zmq.Context.instance() |
|
|
|
ctx = zmq.Context.instance() |
|
|
|
@ -52,11 +68,18 @@ def main(): |
|
|
|
time_delta = datetime.timedelta(seconds=int(args.time_delta)) |
|
|
|
time_delta = datetime.timedelta(seconds=int(args.time_delta)) |
|
|
|
print('Applying delta:', time_delta) |
|
|
|
print('Applying delta:', time_delta) |
|
|
|
line_count = 0 |
|
|
|
line_count = 0 |
|
|
|
|
|
|
|
ticker = None |
|
|
|
with open(args.input_file, 'r') as f: |
|
|
|
with open(args.input_file, 'r') as f: |
|
|
|
reader = csv.reader(f, delimiter=',') |
|
|
|
reader = csv.reader(f, delimiter=',') |
|
|
|
next(reader) |
|
|
|
next(reader) |
|
|
|
for line in reader: |
|
|
|
for line in reader: |
|
|
|
line_count += 1 |
|
|
|
line_count += 1 |
|
|
|
|
|
|
|
if ticker is None: |
|
|
|
|
|
|
|
ticker = line[0] |
|
|
|
|
|
|
|
elif ticker != line[0]: |
|
|
|
|
|
|
|
print('Different tickers in file, aborting') |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
|
|
|
|
date = line[2] |
|
|
|
date = line[2] |
|
|
|
time = line[3] |
|
|
|
time = line[3] |
|
|
|
open_ = line[4] |
|
|
|
open_ = line[4] |
|
|
|
@ -72,8 +95,9 @@ def main(): |
|
|
|
minute = int(time[2:4]) |
|
|
|
minute = int(time[2:4]) |
|
|
|
second = int(time[4:6]) |
|
|
|
second = int(time[4:6]) |
|
|
|
|
|
|
|
|
|
|
|
dt = datetime.datetime(year, month, day, hour, minute, second, 0, datetime.timezone.utc) - time_delta |
|
|
|
dt = datetime.datetime(year, month, day, hour, minute, second, 0, tz) - time_delta |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dt = dt.astimezone(utc_tz) |
|
|
|
serialized_bars.write(struct.pack("<qddddQ", int(dt.timestamp()), float(open_), float(high), float(low), float(close), int(volume))) |
|
|
|
serialized_bars.write(struct.pack("<qddddQ", int(dt.timestamp()), float(open_), float(high), float(low), float(close), int(volume))) |
|
|
|
|
|
|
|
|
|
|
|
if min_dt is None: |
|
|
|
if min_dt is None: |
|
|
|
@ -94,8 +118,23 @@ def main(): |
|
|
|
if args.force_to is not None: |
|
|
|
if args.force_to is not None: |
|
|
|
max_dt = datetime.datetime.strptime(args.force_to, "%Y%m%d") |
|
|
|
max_dt = datetime.datetime.strptime(args.force_to, "%Y%m%d") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
out_ticker = out_symbol |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if out_symbol[0] == '@': |
|
|
|
|
|
|
|
base = out_symbol[1:] |
|
|
|
|
|
|
|
matches = re.match('^([^-]+)-(\\d+)\\.(\\d+)$', ticker) |
|
|
|
|
|
|
|
if not matches: |
|
|
|
|
|
|
|
print('Invalid ticker id in file') |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
year_code = matches.group(3)[:-1] |
|
|
|
|
|
|
|
month_code = get_month_code(int(matches.group(2))) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
out_ticker = base + month_code + year_code |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
print("Resulting ticker: {}".format(out_ticker)) |
|
|
|
|
|
|
|
|
|
|
|
rq = { |
|
|
|
rq = { |
|
|
|
"ticker" : out_symbol, |
|
|
|
"ticker" : out_ticker, |
|
|
|
"start_time" : min_dt.strftime("%Y-%m-%dT%H:%M:%S"), |
|
|
|
"start_time" : min_dt.strftime("%Y-%m-%dT%H:%M:%S"), |
|
|
|
"end_time" : max_dt.strftime("%Y-%m-%dT%H:%M:%S"), |
|
|
|
"end_time" : max_dt.strftime("%Y-%m-%dT%H:%M:%S"), |
|
|
|
"timeframe_sec" : sec_from_period(period) |
|
|
|
"timeframe_sec" : sec_from_period(period) |
|
|
|
@ -108,8 +147,12 @@ def main(): |
|
|
|
s.send_multipart([bytes(json.dumps(rq), "utf-8"), raw_data]) |
|
|
|
s.send_multipart([bytes(json.dumps(rq), "utf-8"), raw_data]) |
|
|
|
parts = s.recv_multipart() |
|
|
|
parts = s.recv_multipart() |
|
|
|
print("Response:", parts) |
|
|
|
print("Response:", parts) |
|
|
|
|
|
|
|
return True |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__': |
|
|
|
if __name__ == '__main__': |
|
|
|
main() |
|
|
|
ret = main() |
|
|
|
|
|
|
|
if ret is None: |
|
|
|
|
|
|
|
sys.exit(1) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|