from dataclasses import dataclass, field
from typing import List
import numpy as np
import pandas as pd
from .market_asset import MarketAsset
[docs]
@dataclass
class OptimizationAsset(MarketAsset):
quantity: float = 0.0 # evitar el error
# Campos derivados que no se pasan al constructor
returns: pd.Series = field(init=False)
log_returns: pd.Series = field(init=False)
mean_return: float = field(init=False)
volatility: float = field(init=False)
def __post_init__(self):
super().__post_init__()
self.returns = self.prices.pct_change().dropna()
self.log_returns = self.prices.pct_change().apply(lambda x: np.log(1 + x))
self.mean_return = self.log_returns.mean()
self.volatility = self.log_returns.std()
[docs]
@classmethod
def to_dataframe(cls, assets: List["OptimizationAsset"]) -> pd.DataFrame:
"""Convert a list of OptimizationAsset objects to a pandas DataFrame."""
if not assets:
return pd.DataFrame()
data = []
for asset in assets:
data.append(
{
"ticker": asset.ticker,
"currency": asset.currency,
"quantity": asset.quantity,
"mean_return": asset.mean_return,
"volatility": asset.volatility,
"returns_length": len(asset.returns),
}
)
return pd.DataFrame(data)
def __repr__(self):
return (
f"OptimizationAsset(ticker={self.ticker}, sector={self.sector}, currency={self.currency}, "
f"quantity={self.quantity}, prices_length={len(self.prices)}, info_keys={list(self.info.keys())})"
)