def get_available_portfolio_dts(self, df, start_dt, end_dt): ''' Gets the available date/datetime points from the range of start_dt and end_dt from the provided dataframe ''' dt1 = start_dt if type(start_dt) == datetime.datetime else str_to_ts( start_dt) if end_dt: dt2 = end_dt if end_dt and type( end_dt) == datetime.datetime else str_to_ts(end_dt) return list(df[(df.index >= dt1) & (df.index <= dt2)].index.unique()) else: return list(df[df.index >= dt1].index.unique())
def _update_signals(signals: pd.DataFrame, df: pd.DataFrame, signal_name: str or None = None): if not signal_name: # Set up a default signal's name if not provided. # Try to define signals_1 as the default name. # Find available signals_n if 'signals_1' is busy. signal_name = "signals_1" while signal_name in signals['signal'].unique(): signal_name = signal_name.split('_')[0] + '_' + str( int(signal_name.split('_')[1]) + 1) df['signal'] = signal_name df['dt'] = df['dt'].apply(lambda x: str_to_ts(x)) if 'trade_percantage' not in df.columns: df['trade_percantage'] = self.default_trade_percantage if 'decision_delay' not in df.columns: df['decision_delay'] = self.decision_delay df['delayed_dt'] = df['dt'] + df['decision_delay'] df.set_index('delayed_dt', inplace=True) df.set_index(df.index.ceil(freq=self._granularity), inplace=True) # df = df['dt', 'signal', 'asset', 'decision_delay', 'trade_percantage'] return signals.append(df)
def __init__(self, start_dt: str or datetime, end_dt: str or datetime or None = None, granularity: str = '1D', decision_delay: int = 0, init_asset: str or None = None, add_asset_once_authorized: bool = False, sell_assets_once_unauthorized: bool = True): self._granularity = granularity self._start_dt = str_to_ts(start_dt) self.end_dt = end_dt self.decision_delay = datetime.timedelta(seconds=decision_delay) self.init_asset = init_asset self.add_asset_once_authorized = add_asset_once_authorized self.sell_assets_once_unauthorized = sell_assets_once_unauthorized self.assets = Assets(start_dt=start_dt, end_dt=end_dt, granularity=granularity, init_asset=init_asset) self.prices = Prices(start_dt=start_dt, end_dt=end_dt, granularity=granularity) self.signals = Signals(start_dt=start_dt, end_dt=end_dt, granularity=granularity, decision_delay=decision_delay) self.portfolio = pd.DataFrame(None) self.asset_shares = pd.DataFrame(None) self.trades_log = pd.DataFrame( columns=['dt', 'order', 'share', 'from', 'to', 'fee', 'metadata'])
def _remove_assets(assets_df, exclude_asset, exclude_dates, granularity=self._granularity): dates = [str_to_ts(dt) for dt in exclude_dates] assert len(dates) % 2 == 0, f'Unsupported datetime sequence for {exclude_asset}: odd amount of dates.' for i in range(int(len(dates) / 2)): exclude_dates = list(pd.date_range(start=dates[2 * i], end=dates[2 * i + 1], freq=granularity)) assets_df = assets_df[ ~((assets_df.index.isin(exclude_dates)) & (assets_df['asset'] == exclude_asset)) ] return assets_df
def __init__(self, start_dt: str or datetime, end_dt: str or datetime or None = None, granularity: str = '1D', decision_delay: int = 0): self._granularity = granularity self._start_dt = str_to_ts(start_dt) self.end_dt = end_dt self.decision_delay = datetime.timedelta(seconds=decision_delay) self.default_trade_percantage = 1 self.buy_signals = self._default_signals_df.copy() self.sell_signals = self._default_signals_df.copy() self.rebalance_signals = self._default_signals_df.copy()
def __init__( self, start_dt: str or datetime, end_dt: str or datetime or None = None, granularity: str = '1D', init_asset: str or None = None, ): self._granularity = granularity self._start_dt = str_to_ts(start_dt) self.end_dt = end_dt self.init_asset = init_asset self.common_assets = pd.DataFrame(columns=['asset']) self.reserve_assets = pd.DataFrame(columns=['asset'])
def __init__( self, start_dt: str or datetime, end_dt: str or datetime or None = None, granularity: str = '1D', fill_gaps_by_default: bool = False, fill_gaps_function: str = 'pad' ): # These parameters could be used later for checking price gaps, interpolation, etc. self._granularity = granularity self._start_dt = str_to_ts(start_dt) self.end_dt = end_dt self.prices = pd.DataFrame(columns=['dt', 'asset', 'price', 'price_change']).set_index('dt') self.fill_gaps_by_default = fill_gaps_by_default self.fill_gaps_function = fill_gaps_function
def _update_assets(assets, new_assets, granularity=self._granularity): ''' Updates assets-in-the-portfolio dataFrame.''' for asset_name in new_assets: # Convert and test datetimes dates = [str_to_ts(dt) for dt in new_assets[asset_name]] assert min(dates) >= self._start_dt, \ f'Provided datetime ({min(dates)}) is smaller than expected ({self._start_dt}). [{asset_name}]' assert len(dates) % 2 == 0, f'Unsupported datetime sequence for {asset_name}: odd amount of dates.' # Update assets in the portfolio for i in range(int(len(dates) / 2)): assets = assets.append(pd.DataFrame( index=pd.date_range(start=dates[2 * i], end=dates[2 * i + 1], freq=granularity), data={'asset': asset_name} )) return assets.reset_index().drop_duplicates().set_index('index').sort_index()
def __init__(self, start_dt: str or datetime.datetime, initial_investment: float = 10**6, default_transfers_limit: int = 1, accuracy: float = 3 * 10**(-6), granularity: str = '1D'): self.start_dt = str_to_ts(start_dt) self.initial_investment = initial_investment self.default_transfers_limit = default_transfers_limit self.accuracy = accuracy self.prices = Prices(start_dt=self.start_dt, granularity=granularity) self.portfolio = pd.DataFrame(None) self.net_returns = pd.DataFrame(None) self.portfolio_price = pd.DataFrame(None) self.trades_log = pd.DataFrame(None) self.fees = pd.DataFrame(None)
def prepare_df(source_df: pd.DataFrame): ''' DF can be provided to the object with dt index or dt column which will be transformed into index. ''' df = source_df.copy() if 'dt' in df.columns: if not is_datetime(df['dt']): df['dt'] = df['dt'].apply(lambda x: str_to_ts(x)) df.set_index('dt', inplace=True) else: if type(df.index) != pd.core.indexes.datetimes.DatetimeIndex: logging.error( 'Please provide a df with datetime index or index data using column named "dt"' ) return else: df.index.name = 'dt' df = df.reset_index() df['dt'] = [item.replace(tzinfo=None) for item in df['dt']] df.set_index('dt', inplace=True) return df