diff --git a/binance/client.py b/binance/client.py index 432a53a30..1fec1f411 100644 --- a/binance/client.py +++ b/binance/client.py @@ -5,7 +5,7 @@ import requests import time from operator import itemgetter -from .helpers import date_to_milliseconds, interval_to_milliseconds +from .helpers import date_to_milliseconds, interval_to_milliseconds, increment_month from .exceptions import BinanceAPIException, BinanceRequestException, BinanceWithdrawException @@ -831,7 +831,10 @@ def get_historical_klines(self, symbol, interval, start_str, end_str=None, break # increment next call by our timeframe - start_ts += timeframe + if interval == self.KLINE_INTERVAL_1MONTH: + start_ts = increment_month(start_ts) + else: + start_ts += timeframe # sleep after every 3rd call to be kind to the API if idx % 3 == 0: @@ -912,7 +915,10 @@ def get_historical_klines_generator(self, symbol, interval, start_str, end_str=N break # increment next call by our timeframe - start_ts += timeframe + if interval == self.KLINE_INTERVAL_1MONTH: + start_ts = increment_month(start_ts) + else: + start_ts += timeframe # sleep after every 3rd call to be kind to the API if idx % 3 == 0: diff --git a/binance/helpers.py b/binance/helpers.py index fe91df3f4..d92ad5621 100644 --- a/binance/helpers.py +++ b/binance/helpers.py @@ -4,6 +4,7 @@ import pytz from datetime import datetime +from dateutil.relativedelta import relativedelta def date_to_milliseconds(date_str): @@ -50,3 +51,20 @@ def interval_to_milliseconds(interval): return int(interval[:-1]) * seconds_per_unit[interval[-1]] * 1000 except (ValueError, KeyError): return None + + +def increment_month(origin_ts): + """Increment a given timestamp by one month + + :param origin_ts: original timestamp, e.g.: 1501545600000, 1504224000000, ... + :type origin_ts: int + + :return: + Timestamp incremented by one month from a given timestamp + """ + d = datetime.fromtimestamp(origin_ts/1000) + relativedelta(months=1) + # if the date is not timezone aware apply UTC timezone + if d.tzinfo is None or d.tzinfo.utcoffset(d) is None: + d = d.replace(tzinfo=pytz.utc) + + return int(datetime.timestamp(d)) diff --git a/docs/helpers.rst b/docs/helpers.rst index 2820ff65f..6981244f5 100644 --- a/docs/helpers.rst +++ b/docs/helpers.rst @@ -2,5 +2,5 @@ Helper Functions ================ .. autoclass:: binance.helpers - :members: date_to_milliseconds, interval_to_milliseconds + :members: date_to_milliseconds, interval_to_milliseconds, increment_month :noindex: diff --git a/examples/save_historical_data.py b/examples/save_historical_data.py index c5aebecd8..502520912 100644 --- a/examples/save_historical_data.py +++ b/examples/save_historical_data.py @@ -4,6 +4,8 @@ import json from datetime import datetime + +from dateutil.relativedelta import relativedelta from binance.client import Client @@ -57,6 +59,23 @@ def interval_to_milliseconds(interval): return ms +def increment_month(origin_ts): + """Increment a given timestamp by one month + + :param origin_ts: original timestamp, e.g.: 1501545600000, 1504224000000, ... + :type origin_ts: int + + :return: + Timestamp incremented by one month from a given timestamp + """ + d = datetime.fromtimestamp(origin_ts/1000) + relativedelta(months=1) + # if the date is not timezone aware apply UTC timezone + if d.tzinfo is None or d.tzinfo.utcoffset(d) is None: + d = d.replace(tzinfo=pytz.utc) + + return int(datetime.timestamp(d)) + + def get_historical_klines(symbol, interval, start_str, end_str=None): """Get Historical Klines from Binance @@ -118,10 +137,16 @@ def get_historical_klines(symbol, interval, start_str, end_str=None): output_data += temp_data # update our start timestamp using the last value in the array and add the interval timeframe - start_ts = temp_data[len(temp_data) - 1][0] + timeframe + if interval == Client.KLINE_INTERVAL_1MONTH: + start_ts = increment_month(temp_data[len(temp_data) - 1][0]) + else: + start_ts = temp_data[len(temp_data) - 1][0] + timeframe else: # it wasn't listed yet, increment our start date - start_ts += timeframe + if interval == Client.KLINE_INTERVAL_1MONTH: + start_ts = increment_month(start_ts) + else: + start_ts += timeframe idx += 1 # check if we received less than the required limit and exit the loop