Source code for alchemist_lib.datafeed.bittrexdatafeed

from bittrex.bittrex import Bittrex

import pandas as pd

import urllib.request as req

import json

import datetime as dt

import time

from decimal import Decimal

from .ohlcv import OhlcvBaseClass

from ..database.ohlcv import Ohlcv
from ..database.price_data_source import PriceDataSource
from ..database.timeframe import Timeframe
from ..database.asset import Asset
from ..database.instrument import Instrument

from .. import utils

import logging



[docs]class BittrexDataFeed(OhlcvBaseClass): """ Class that manages data collecting from Bittrex. Inherits from alchemist_lib.datafeed.ohlcv.OhlcvBaseClass. Website: https://bittrex.com/ Api documentation: https://bittrex.com/Home/Api Api wrapper: https://github.com/ericsomdahl/python-bittrex Attributes: session (sqlalchemy.orm.session.Session): Database connection. bittrex (bittrex.bittrex.Bittrex): Communication object. """ sleep_seconds = 0.4 available_timeframe = {"1M" : "oneMin", "5M" : "fiveMin", "30M" : "thirtyMin", "1H" : "hour", "1D" : "day" }
[docs] def __init__(self, session): """ Costructor method. Args: session (sqlalchemy.orm.session.Session): Connection to the database. """ OhlcvBaseClass.__init__(self, session = session) self.bittrex = Bittrex(api_key = None, api_secret = None)
[docs] def get_assets(self): """ Return the list of asset traded. Return: assets (list[alchemist_lib.database.asset.Asset]): List of assets. Note: Return only pairs with bitcoin as base currency. """ markets = self.bittrex.get_markets() if markets["result"] == None: logging.warning("Bittrex api result is None. get_assets() method.") return [] cryptocurrency_id = self.session.query(Instrument.instrument_id).filter(Instrument.instrument_type == "cryptocurrency").one().instrument_id assets = [] for market in markets["result"]: if market["BaseCurrency"] == "BTC": asset = Asset(ticker = market["MarketCurrency"], instrument_id = cryptocurrency_id, name = market["MarketCurrencyLong"]) assets.append(asset) return assets
[docs] def get_last_price(self, assets): """ Retrieve last price of the list of assets passed. Args: assets (alchemist_lib.database.asset.Asset, list[Asset]): List of assets which we want the last trade price of. Return: df (pandas.DataFrame): A dataframe with the following columns: * asset (alchemist_lib.database.asset.Asset): Must be the index. * last_price (decimal.Decimal): The last price of the associated asset. If some prices are not retrieved the last_price attribute will be 0. """ assets = utils.to_list(assets) market_summaries = self.bittrex.get_market_summaries() if market_summaries["result"] == None or market_summaries["success"] == False: logging.warning("Bittrex api result is None or success is False. get_last_price() method.") return pd.DataFrame(data = {"asset" : assets, "last_price" : Decimal(0)}, columns = ["asset", "last_price"]).set_index("asset") market_summaries = market_summaries["result"] df = pd.DataFrame(data = {"asset" : assets}, columns = ["asset", "last_price"]).set_index("asset") for asset in assets: pair = "BTC-{}".format(asset.ticker) found = False for market in market_summaries: if market["MarketName"] == pair: df.loc[asset, "last_price"] = Decimal(market["Last"]) found = True if found == False: logging.debug("{} market not found. last_price will be 0.".format(pair)) df.loc[asset, "last_price"] = Decimal(0) else: logging.debug("{} last price: {}".format(asset.ticker, df.loc[asset, "last_price"])) return df
[docs] def get_ohlcv(self, assets, start_date, timeframe, end_date = dt.datetime.utcnow()): """ Collect ohlcv data from start_date to end_date for every asset. Args: assets (list[alchemist_lib.database.asset.Asset]): List of assets. start_date (datetime.datetime): Datetime to start collecting data from. end_date (datetime.datetime, optional): Datetime to end collecting data from. Default is utcnow(). timeframe (str): Timeframe identifier. Return: candles (list[alchemist_lib.database.ohlcv.Ohlcv]): List of ohlcv data. """ assets = utils.to_list(assets) timeframe = timeframe.upper() availble_timeframes = [ds.available_timeframes for ds in self.session.query(PriceDataSource).join((Timeframe, PriceDataSource.available_timeframes)).filter(PriceDataSource.price_data_source_name == "bittrex").all()] assert timeframe not in availble_timeframes, "Timeframe not available for BittrexDataFeed." end_point = "https://bittrex.com/Api/v2.0/pub/market/GetTicks" candles = [] for asset in assets: url = end_point + "?marketName=BTC-{}&tickInterval={}".format(asset.ticker, BittrexDataFeed.available_timeframe[timeframe]) json_data = req.urlopen(url) data = json.loads(json_data.read().decode("UTF-8")) results = data["result"] if results == None: logging.warning("Bittrex api result is None. get_ohlcv() method. Asset: {}".format(asset.ticker)) continue results = [item for item in results if dt.datetime.strptime(item["T"], '%Y-%m-%dT%H:%M:%S') < end_date and dt.datetime.strptime(item["T"], '%Y-%m-%dT%H:%M:%S') > start_date] for row in results: candle = Ohlcv() candle.ohlcv_datetime = dt.datetime.strptime(row["T"], '%Y-%m-%dT%H:%M:%S') candle.timeframe_id = timeframe candle.open = Decimal(row["O"]) candle.high = Decimal(row["H"]) candle.low = Decimal(row["L"]) candle.close = Decimal(row["C"]) candle.volume = Decimal(row["V"]) candle.ticker = asset.ticker candle.instrument_id = asset.instrument_id candles.append(candle) time.sleep(BittrexDataFeed.sleep_seconds) return candles