Skip to content

Commit

Permalink
Updated to use mbinary constants for float storage.
Browse files Browse the repository at this point in the history
  • Loading branch information
anthonyb8 committed Feb 10, 2025
1 parent 3214e86 commit 15a4a05
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 90 deletions.
85 changes: 42 additions & 43 deletions midastrader/core/adapters/performance/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@
import threading
import pandas as pd
from datetime import datetime
from mbinary import BacktestData
from mbinary import BacktestData, PRICE_SCALE
from midas_client.client import DatabaseClient

from midastrader.structs.symbol import SymbolMap
from midastrader.config import Parameters, Mode
from midastrader.core.adapters.base_strategy import BaseStrategy
from midastrader.utils.unix import unix_to_iso
from midastrader.structs.constants import PRICE_FACTOR
from midastrader.message_bus import MessageBus, EventType
from midastrader.structs.events import TradeCommissionEvent, TradeEvent
from midastrader.core.adapters.base import CoreAdapter
Expand Down Expand Up @@ -295,7 +294,7 @@ def mbinary_static_stats(self, static_stats: dict) -> mbinary.StaticStats:
Converts static performance statistics into an `mbinary.StaticStats` object.
Behavior:
- Scales all percentage and ratio metrics using a `PRICE_FACTOR`.
- Scales all percentage and ratio metrics using a `PRICE_SCALE`.
- Creates an `mbinary.StaticStats` object with all relevant performance statistics.
Args:
Expand All @@ -309,51 +308,51 @@ def mbinary_static_stats(self, static_stats: dict) -> mbinary.StaticStats:
total_trades=static_stats["total_trades"],
total_winning_trades=static_stats["total_winning_trades"],
total_losing_trades=static_stats["total_losing_trades"],
avg_profit=int(static_stats["avg_profit"] * PRICE_FACTOR),
avg_profit=int(static_stats["avg_profit"] * PRICE_SCALE),
avg_profit_percent=int(
static_stats["avg_profit_percent"] * PRICE_FACTOR
static_stats["avg_profit_percent"] * PRICE_SCALE
),
avg_gain=int(static_stats["avg_gain"] * PRICE_FACTOR),
avg_gain=int(static_stats["avg_gain"] * PRICE_SCALE),
avg_gain_percent=int(
static_stats["avg_gain_percent"] * PRICE_FACTOR
static_stats["avg_gain_percent"] * PRICE_SCALE
),
avg_loss=int(static_stats["avg_loss"] * PRICE_FACTOR),
avg_loss=int(static_stats["avg_loss"] * PRICE_SCALE),
avg_loss_percent=int(
static_stats["avg_loss_percent"] * PRICE_FACTOR
static_stats["avg_loss_percent"] * PRICE_SCALE
),
profitability_ratio=int(
static_stats["profitability_ratio"] * PRICE_FACTOR
static_stats["profitability_ratio"] * PRICE_SCALE
),
profit_factor=int(static_stats["profit_factor"] * PRICE_FACTOR),
profit_factor=int(static_stats["profit_factor"] * PRICE_SCALE),
profit_and_loss_ratio=int(
static_stats["profit_and_loss_ratio"] * PRICE_FACTOR
static_stats["profit_and_loss_ratio"] * PRICE_SCALE
),
total_fees=int(static_stats["total_fees"] * PRICE_FACTOR),
net_profit=int(static_stats["net_profit"] * PRICE_FACTOR),
total_fees=int(static_stats["total_fees"] * PRICE_SCALE),
net_profit=int(static_stats["net_profit"] * PRICE_SCALE),
beginning_equity=int(
static_stats["beginning_equity"] * PRICE_FACTOR
static_stats["beginning_equity"] * PRICE_SCALE
),
ending_equity=int(static_stats["ending_equity"] * PRICE_FACTOR),
total_return=int(static_stats["total_return"] * PRICE_FACTOR),
ending_equity=int(static_stats["ending_equity"] * PRICE_SCALE),
total_return=int(static_stats["total_return"] * PRICE_SCALE),
annualized_return=int(
static_stats["annualized_return"] * PRICE_FACTOR
static_stats["annualized_return"] * PRICE_SCALE
),
daily_standard_deviation_percentage=int(
static_stats["daily_standard_deviation_percentage"]
* PRICE_FACTOR
* PRICE_SCALE
),
annual_standard_deviation_percentage=int(
static_stats["annual_standard_deviation_percentage"]
* PRICE_FACTOR
* PRICE_SCALE
),
max_drawdown_percentage_period=int(
static_stats["max_drawdown_percentage_period"] * PRICE_FACTOR
static_stats["max_drawdown_percentage_period"] * PRICE_SCALE
),
max_drawdown_percentage_daily=int(
static_stats["max_drawdown_percentage_daily"] * PRICE_FACTOR
static_stats["max_drawdown_percentage_daily"] * PRICE_SCALE
),
sharpe_ratio=int(static_stats["sharpe_ratio"] * PRICE_FACTOR),
sortino_ratio=int(static_stats["sortino_ratio"] * PRICE_FACTOR),
sharpe_ratio=int(static_stats["sharpe_ratio"] * PRICE_SCALE),
sortino_ratio=int(static_stats["sortino_ratio"] * PRICE_SCALE),
)

def generate_backtest_name(self) -> str:
Expand Down Expand Up @@ -423,7 +422,7 @@ def mbinary_account_summary(self, account: dict) -> mbinary.AccountSummary:
Converts account summary data into an `mbinary.AccountSummary` object.
Behavior:
- Scales monetary and percentage metrics using a `PRICE_FACTOR`.
- Scales monetary and percentage metrics using a `PRICE_SCALE`.
- Populates `mbinary.AccountSummary` with fields for both start and end timestamps, buying power,
liquidity, margin requirements, PnL, cash balance, and net liquidation values.
Expand All @@ -437,53 +436,53 @@ def mbinary_account_summary(self, account: dict) -> mbinary.AccountSummary:
currency=account["currency"],
start_timestamp=int(account["start_timestamp"]),
start_buying_power=int(
account["start_buying_power"] * PRICE_FACTOR
account["start_buying_power"] * PRICE_SCALE
),
start_excess_liquidity=int(
account["start_excess_liquidity"] * PRICE_FACTOR
account["start_excess_liquidity"] * PRICE_SCALE
),
start_full_available_funds=int(
account["start_full_available_funds"] * PRICE_FACTOR
account["start_full_available_funds"] * PRICE_SCALE
),
start_full_init_margin_req=int(
account["start_full_init_margin_req"] * PRICE_FACTOR
account["start_full_init_margin_req"] * PRICE_SCALE
),
start_full_maint_margin_req=int(
account["start_full_maint_margin_req"] * PRICE_FACTOR
account["start_full_maint_margin_req"] * PRICE_SCALE
),
start_futures_pnl=int(account["start_futures_pnl"] * PRICE_FACTOR),
start_futures_pnl=int(account["start_futures_pnl"] * PRICE_SCALE),
start_net_liquidation=int(
account["start_net_liquidation"] * PRICE_FACTOR
account["start_net_liquidation"] * PRICE_SCALE
),
start_total_cash_balance=int(
account["start_total_cash_balance"] * PRICE_FACTOR
account["start_total_cash_balance"] * PRICE_SCALE
),
start_unrealized_pnl=int(
account["start_unrealized_pnl"] * PRICE_FACTOR
account["start_unrealized_pnl"] * PRICE_SCALE
),
end_timestamp=int(account["end_timestamp"]),
end_buying_power=int(account["end_buying_power"] * PRICE_FACTOR),
end_buying_power=int(account["end_buying_power"] * PRICE_SCALE),
end_excess_liquidity=int(
account["end_excess_liquidity"] * PRICE_FACTOR
account["end_excess_liquidity"] * PRICE_SCALE
),
end_full_available_funds=int(
account["end_full_available_funds"] * PRICE_FACTOR
account["end_full_available_funds"] * PRICE_SCALE
),
end_full_init_margin_req=int(
account["end_full_init_margin_req"] * PRICE_FACTOR
account["end_full_init_margin_req"] * PRICE_SCALE
),
end_full_maint_margin_req=int(
account["end_full_maint_margin_req"] * PRICE_FACTOR
account["end_full_maint_margin_req"] * PRICE_SCALE
),
end_futures_pnl=int(account["end_futures_pnl"] * PRICE_FACTOR),
end_futures_pnl=int(account["end_futures_pnl"] * PRICE_SCALE),
end_net_liquidation=int(
account["end_net_liquidation"] * PRICE_FACTOR
account["end_net_liquidation"] * PRICE_SCALE
),
end_total_cash_balance=int(
account["end_total_cash_balance"] * PRICE_FACTOR
account["end_total_cash_balance"] * PRICE_SCALE
),
end_unrealized_pnl=int(
account["end_unrealized_pnl"] * PRICE_FACTOR
account["end_unrealized_pnl"] * PRICE_SCALE
),
)

Expand Down
22 changes: 9 additions & 13 deletions midastrader/core/adapters/performance/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import numpy as np
import pandas as pd
from typing import List, Dict
from mbinary import PRICE_SCALE
from quant_analytics.backtest.metrics import Metrics

from midastrader.structs.trade import Trade
Expand All @@ -13,7 +14,6 @@
from midastrader.utils.unix import resample_timestamp
from midastrader.structs.account import EquityDetails, Account
from midastrader.structs.symbol import SymbolMap
from midastrader.structs.constants import PRICE_FACTOR
from midastrader.utils.logger import SystemLogger


Expand Down Expand Up @@ -559,12 +559,10 @@ def period_stats_mbinary(self) -> List[mbinary.TimeseriesStats]:
return [
mbinary.TimeseriesStats(
timestamp=stat["timestamp"],
equity_value=int(stat["equity_value"] * PRICE_FACTOR),
percent_drawdown=int(stat["percent_drawdown"] * PRICE_FACTOR),
cumulative_return=int(
stat["cumulative_return"] * PRICE_FACTOR
),
period_return=int(stat["period_return"] * PRICE_FACTOR),
equity_value=int(stat["equity_value"] * PRICE_SCALE),
percent_drawdown=int(stat["percent_drawdown"] * PRICE_SCALE),
cumulative_return=int(stat["cumulative_return"] * PRICE_SCALE),
period_return=int(stat["period_return"] * PRICE_SCALE),
)
for stat in self.period_stats_dict
]
Expand All @@ -580,12 +578,10 @@ def daily_stats_mbinary(self) -> List[mbinary.TimeseriesStats]:
return [
mbinary.TimeseriesStats(
timestamp=stat["timestamp"],
equity_value=int(stat["equity_value"] * PRICE_FACTOR),
percent_drawdown=int(stat["percent_drawdown"] * PRICE_FACTOR),
cumulative_return=int(
stat["cumulative_return"] * PRICE_FACTOR
),
period_return=int(stat["period_return"] * PRICE_FACTOR),
equity_value=int(stat["equity_value"] * PRICE_SCALE),
percent_drawdown=int(stat["percent_drawdown"] * PRICE_SCALE),
cumulative_return=int(stat["cumulative_return"] * PRICE_SCALE),
period_return=int(stat["period_return"] * PRICE_SCALE),
)
for stat in self.daily_stats_dict
]
Expand Down
2 changes: 0 additions & 2 deletions midastrader/structs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from .account import EquityDetails, Account
from .active_orders import ActiveOrder, OrderStatus
from .constants import PRICE_FACTOR
from .orders import (
Action,
OrderType,
Expand Down Expand Up @@ -43,7 +42,6 @@
"Account",
"ActiveOrder",
"OrderStatus",
"PRICE_FACTOR",
"Action",
"OrderType",
"BaseOrder",
Expand Down
4 changes: 0 additions & 4 deletions midastrader/structs/constants.py

This file was deleted.

6 changes: 3 additions & 3 deletions midastrader/structs/signal.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import mbinary
from dataclasses import dataclass
from typing import Optional
from mbinary import PRICE_SCALE, QUANTITY_SCALE

from midastrader.structs.constants import PRICE_FACTOR, QUANTITY_FACATOR
from midastrader.structs.orders import (
OrderType,
Action,
Expand Down Expand Up @@ -129,8 +129,8 @@ def to_mbinary(self, ticker: str) -> mbinary.SignalInstructions:
action=self.action.value,
trade_id=self.signal_id,
leg_id=self.signal_id,
weight=int(self.weight * PRICE_FACTOR),
quantity=int(self.quantity * QUANTITY_FACATOR),
weight=int(self.weight * PRICE_SCALE),
quantity=int(self.quantity * QUANTITY_SCALE),
limit_price=str(self.limit_price) if self.limit_price else "",
aux_price=str(self.aux_price) if self.aux_price else "",
)
Expand Down
14 changes: 8 additions & 6 deletions midastrader/structs/trade.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import mbinary
from dataclasses import dataclass
from mbinary import PRICE_SCALE

from midastrader.structs.constants import PRICE_FACTOR
from midastrader.structs.symbol import SecurityType

# from midastrader.structs.constants import PRICE_SCALE


@dataclass
class Trade:
Expand Down Expand Up @@ -115,12 +117,12 @@ def to_mbinary(self, ticker: str) -> mbinary.Trades:
leg_id=self.signal_id,
timestamp=self.timestamp,
ticker=ticker,
quantity=int(self.quantity * PRICE_FACTOR),
avg_price=int(self.avg_price * PRICE_FACTOR),
trade_value=int(self.trade_value * PRICE_FACTOR),
trade_cost=int(self.trade_cost * PRICE_FACTOR),
quantity=int(self.quantity * PRICE_SCALE),
avg_price=int(self.avg_price * PRICE_SCALE),
trade_value=int(self.trade_value * PRICE_SCALE),
trade_cost=int(self.trade_cost * PRICE_SCALE),
action=self.action,
fees=int(self.fees * PRICE_FACTOR),
fees=int(self.fees * PRICE_SCALE),
)

def pretty_print(self, indent: str = "") -> str:
Expand Down
38 changes: 19 additions & 19 deletions tests/unit/core/performance/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from time import sleep
import threading
from datetime import time
from mbinary import PRICE_SCALE
from unittest.mock import Mock, MagicMock

from midastrader.structs.events.market_event import MarketEvent
Expand All @@ -23,7 +24,6 @@
from midastrader.structs.orders import OrderType, Action
from midastrader.structs.signal import SignalInstruction
from midastrader.core.adapters.base_strategy import BaseStrategy
from midastrader.structs.constants import PRICE_FACTOR
from midastrader.structs.symbol import (
Equity,
Currency,
Expand Down Expand Up @@ -583,25 +583,25 @@ def test_save_live(self):
# Validate account
expected_account = mbinary.AccountSummary(
start_timestamp=165000000000,
start_full_available_funds=int(768953.53 * PRICE_FACTOR),
start_full_init_margin_req=int(263.95 * PRICE_FACTOR),
start_net_liquidation=int(769217.48 * PRICE_FACTOR),
start_buying_power=int(2563178.43 * PRICE_FACTOR),
start_unrealized_pnl=int(0.00 * PRICE_FACTOR),
start_full_maint_margin_req=int(263.95 * PRICE_FACTOR),
start_excess_liquidity=int(768953.53 * PRICE_FACTOR),
start_futures_pnl=int(-367.50 * PRICE_FACTOR),
start_total_cash_balance=int(-10557.9223 * PRICE_FACTOR),
start_full_available_funds=int(768953.53 * PRICE_SCALE),
start_full_init_margin_req=int(263.95 * PRICE_SCALE),
start_net_liquidation=int(769217.48 * PRICE_SCALE),
start_buying_power=int(2563178.43 * PRICE_SCALE),
start_unrealized_pnl=int(0.00 * PRICE_SCALE),
start_full_maint_margin_req=int(263.95 * PRICE_SCALE),
start_excess_liquidity=int(768953.53 * PRICE_SCALE),
start_futures_pnl=int(-367.50 * PRICE_SCALE),
start_total_cash_balance=int(-10557.9223 * PRICE_SCALE),
end_timestamp=166000000000,
end_full_available_funds=int(762459.99 * PRICE_FACTOR),
end_full_init_margin_req=int(6802.69 * PRICE_FACTOR),
end_net_liquidation=int(769262.67 * PRICE_FACTOR),
end_unrealized_pnl=int(-11.73 * PRICE_FACTOR),
end_full_maint_margin_req=int(5495.00 * PRICE_FACTOR),
end_excess_liquidity=int(763767.68 * PRICE_FACTOR),
end_buying_power=int(2541533.29 * PRICE_FACTOR),
end_futures_pnl=int(-373.30 * PRICE_FACTOR),
end_total_cash_balance=int(768538.5532 * PRICE_FACTOR),
end_full_available_funds=int(762459.99 * PRICE_SCALE),
end_full_init_margin_req=int(6802.69 * PRICE_SCALE),
end_net_liquidation=int(769262.67 * PRICE_SCALE),
end_unrealized_pnl=int(-11.73 * PRICE_SCALE),
end_full_maint_margin_req=int(5495.00 * PRICE_SCALE),
end_excess_liquidity=int(763767.68 * PRICE_SCALE),
end_buying_power=int(2541533.29 * PRICE_SCALE),
end_futures_pnl=int(-373.30 * PRICE_SCALE),
end_total_cash_balance=int(768538.5532 * PRICE_SCALE),
currency="USD",
)

Expand Down

0 comments on commit 15a4a05

Please sign in to comment.