Source code for alchemist_lib.portfolio.longsonly

import numpy as np
from decimal import Decimal, DivisionByZero

from ..database.ptf_allocation import PtfAllocation

from .portfolio import PortfolioBaseClass

from .. import datafeed



[docs]class LongsOnlyPortfolio(PortfolioBaseClass): """ Class that manages the creation of a portfolio of longs-only positions. Inherits from alchemist_lib.portfolio.portfolio.PortfolioBaseClass. Attributes: capital (decimal.Decimal): Capital allocated for the portfolio. """
[docs] def __init__(self, capital): """ Costructor method. Args: capital (int, float, str, decimal.Decimal): Capital allocated for the portfolio. """ PortfolioBaseClass.__init__(self, capital = capital)
[docs] def set_allocation(self, session, name, df): """ Return a list of allocations (alchemist_lib.database.ptf_allocation.PtfAllocation) based on the weight of every asset. Args: session (sqlalchemy.orm.session.Session): Connection to the database. name (str): Name of the trading system. df (pandas.DataFrame): A dataframe with the following columns: * asset (alchemist_lib.database.asset.Asset): Must be the index. * weight (decimal.Decimal): The weight of the specified asset in the portfolio. The sum of all weights in the dataframe must be near 1. Return: allocs (list[PtfAllocation]): List of allocations (ideal portfolio). """ assert df.index.name == "asset", "The set_allocation function must receive a dataframe with the column 'asset' as index." assert "weight" in df.columns, "The set_allocation function must receive a dataframe with a column called 'weight'." my_df = df.copy() last_price = datafeed.get_last_price(assets = my_df.index.values) my_df["amount"] = np.nan my_df["base_currency_amount"] = np.nan for asset, weight in zip(my_df.index.values, my_df["weight"]): base_currency_amount = Decimal(weight) * Decimal(self.capital) my_df.loc[asset, "base_currency_amount"] = base_currency_amount try: if asset.instrument.instrument_type != "cryptocurrency": my_df.loc[asset, "amount"] = Decimal(int(base_currency_amount) / last_price.loc[asset, "last_price"]) else: my_df.loc[asset, "amount"] = Decimal(base_currency_amount / last_price.loc[asset, "last_price"]) except DivisionByZero: my_df.loc[asset, "amount"] = Decimal(0) my_df.drop(labels = ["weight"], axis = 1, inplace = True) my_df["name"] = name allocs = PtfAllocation.from_dataframe(session = session, df = my_df) return allocs