Source code for alchemist_lib.datafeed.ohlcv

from abc import ABC, abstractmethod
import datetime as dt

from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm.exc import FlushError

from .. import utils

import logging



[docs]class OhlcvBaseClass(ABC): """ Abstract class used by modules that manage OHLCV data. Abstract methods: - get_last_price(assets): It has to return a dataframe (pandas.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. - get_ohlcv(assets, start_date, end_date, timeframe): It has to return a list of Ohlcv (alchemist_lib.database.ohlcv.Ohlcv). Attributes: session (sqlalchemy.orm.session.Session): Database connection. """
[docs] def __init__(self, session): """ Costructor method. Args: session (sqlalchemy.orm.session.Session): Connection to the database. """ self.session = session
@abstractmethod def get_last_price(self, assets): pass @abstractmethod def get_ohlcv(self, assets, start_date, timeframe, end_date = dt.datetime.utcnow()): pass
[docs] def _save(self, data): """ Save records in the database. This method doesn't use ``self.session.add_all(data)`` because some objects could raise sqlalchemy.exc.IntegrityError and so nothing will be saved. Save an object per time allow us to pass away IntegrityError. Args: data (list[obj]): List of map class instances. """ for obj in data: try: self.session.add(obj) self.session.commit() except (IntegrityError, FlushError) as e: self.session.rollback()
#logging.debug("An object can't be saved. Obj: {}. Exception: {}".format(obj, e))
[docs] def save_ohlcv(self, assets, start_date, timeframe, end_date = dt.datetime.utcnow()): """ This method collects and saves OHLCV data from the data source. Args: assets (alchemist_lib.database.asset.Asset, list[Asset]): List of assets which we want informations of. 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. """ candles = self.get_ohlcv(assets = assets, start_date = start_date, end_date = end_date, timeframe = timeframe) self._save(data = candles)
[docs] def get_last_ohlcv(self, assets, timeframe): """ This method collects the last OHLCV candle from the data source. Args: assets (alchemist_lib.database.asset.Asset, list[Asset]): List of assets which we want informations of. timeframe (str): Timeframe identifier. Return: candles (list[alchemist_lib.database.ohlcv.Ohlcv]): List of ohlcv data. """ candles = [] for asset in assets: now = dt.datetime.utcnow() if asset.instrument.instrument_type == "cryptocurrency": delta = dt.timedelta(seconds = utils.timeframe_to_seconds(timeframe = timeframe)) past = now - delta candles += self.get_ohlcv(assets = asset, start_date = past, end_date = now, timeframe = timeframe) else: logging.critical("The instrument is not a cryptocurrency. NotImplemented raised.") raise NotImplemented return candles
[docs] def save_last_ohlcv(self, assets, timeframe): """ This method collects and saves last OHLCV candle from the data source. Args: assets (alchemist_lib.database.asset.Asset, list[Asset]): List of assets which we want informations of. timeframe (str): Timeframe identifier. """ candles = self.get_last_ohlcv(assets = assets, timeframe = timeframe) self._save(data = candles)