Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

545 strategy backtests add financial metrics #548

Merged
merged 15 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ape-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ default_ecosystem: gnosis
node:
gnosis:
mainnet:
uri: https://rpc.gnosischain.com
uri: https://rpc.gnosis.gateway.fm #https://rpc.gnosischain.com
gabrielfior marked this conversation as resolved.
Show resolved Hide resolved


networks:
Expand Down
24 changes: 24 additions & 0 deletions examples/monitor/data_models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from pydantic import BaseModel
gabrielfior marked this conversation as resolved.
Show resolved Hide resolved

from prediction_market_agent_tooling.tools.datetime_utc import DatetimeUTC


class SimulationDetail(BaseModel):
strategy: str
url: str
market_p_yes: float
agent_p_yes: float
agent_conf: float
org_bet: float
sim_bet: float
org_dir: bool
sim_dir: bool
org_profit: float
sim_profit: float
timestamp: DatetimeUTC
gabrielfior marked this conversation as resolved.
Show resolved Hide resolved


class SharpeOutput(BaseModel):
annualized_volatility: float
mean_daily_return: float
annualized_sharpe_ratio: float
gabrielfior marked this conversation as resolved.
Show resolved Hide resolved
63 changes: 63 additions & 0 deletions examples/monitor/financial_metrics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import numpy as np
import pandas as pd

from examples.monitor.data_models import SharpeOutput, SimulationDetail


class SharpeRatioCalculator:
gabrielfior marked this conversation as resolved.
Show resolved Hide resolved
def __init__(
self, details: list[SimulationDetail], risk_free_rate: float = 0.0
) -> None:
self.details = details
self.df = pd.DataFrame([d.model_dump() for d in self.details])
self.risk_free_rate = risk_free_rate

def __has_df_valid_columns_else_exception(
self, required_columns: list[str]
) -> None:
if not set(required_columns).issubset(self.df.columns):
raise ValueError("Dataframe doesn't contain all the required columns.")

def prepare_wallet_daily_balance_df(
self, timestamp_col_name: str, profit_col_name: str
) -> pd.DataFrame:
self.__has_df_valid_columns_else_exception(
[timestamp_col_name, profit_col_name]
)
df = self.df.copy()
df[timestamp_col_name] = pd.to_datetime(df[timestamp_col_name])
df.sort_values(timestamp_col_name, ascending=True, inplace=True)

df["profit_cumsum"] = df[profit_col_name].cumsum()
df["profit_cumsum"] = df["profit_cumsum"] + 50

df = df.drop_duplicates(subset=timestamp_col_name, keep="last")
df.set_index(timestamp_col_name, inplace=True)
# We generate a new Dataframe with daily wallet balances, derived by the final wallet balance
# from the previous day.
wallet_balance_daily_df = df[["profit_cumsum"]].resample("D").ffill()
wallet_balance_daily_df.dropna(inplace=True)
wallet_balance_daily_df["returns"] = wallet_balance_daily_df[
"profit_cumsum"
].pct_change()
return wallet_balance_daily_df

def calculate_annual_sharpe_ratio(
self, timestamp_col_name: str = "timestamp", profit_col_name: str = "sim_profit"
) -> SharpeOutput:
wallet_daily_balance_df = self.prepare_wallet_daily_balance_df(
timestamp_col_name=timestamp_col_name, profit_col_name=profit_col_name
)

daily_volatility = wallet_daily_balance_df["returns"].std()
annualized_volatility = daily_volatility * np.sqrt(365)
mean_daily_return = wallet_daily_balance_df["returns"].mean()
daily_sharpe_ratio = (
mean_daily_return - self.risk_free_rate
) / daily_volatility
annualized_sharpe_ratio = daily_sharpe_ratio * np.sqrt(365)
return SharpeOutput(
annualized_volatility=annualized_volatility,
mean_daily_return=mean_daily_return,
annualized_sharpe_ratio=annualized_sharpe_ratio,
)
Loading
Loading