Skip to content

Commit f5b4b40

Browse files
committed
fix: portfolio metrics calculation
1 parent 704331d commit f5b4b40

File tree

2 files changed

+27
-18
lines changed

2 files changed

+27
-18
lines changed

python/valuecell/agents/common/trading/_internal/runtime.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -115,17 +115,20 @@ async def create_strategy_runtime(
115115
# Create strategy runtime components
116116
strategy_id = strategy_id_override or generate_uuid("strategy")
117117

118-
# If an initial capital override wasn't provided, and this is a resume
119-
# of an existing strategy, attempt to initialize from the persisted
120-
# portfolio snapshot so the in-memory portfolio starts with the
121-
# previously recorded equity.
122-
initial_capital_override = None
118+
# If this is a resume of an existing strategy,
119+
# attempt to initialize from the persisted portfolio snapshot
120+
# so the in-memory portfolio starts with the previously recorded equity.
121+
free_cash_override = None
122+
total_cash_override = None
123123
if strategy_id_override:
124124
try:
125125
repo = get_strategy_repository()
126126
snap = repo.get_latest_portfolio_snapshot(strategy_id_override)
127127
if snap is not None:
128-
initial_capital_override = float(snap.total_value or snap.cash or 0.0)
128+
free_cash_override = float(snap.cash or 0.0)
129+
total_cash_override = float(
130+
snap.total_value - snap.total_unrealized_pnl or 0.0
131+
)
129132
logger.info(
130133
"Initialized runtime initial_capital from persisted snapshot for strategy_id=%s",
131134
strategy_id_override,
@@ -136,15 +139,15 @@ async def create_strategy_runtime(
136139
strategy_id_override,
137140
)
138141

139-
initial_capital = (
140-
initial_capital_override or request.trading_config.initial_capital or 0.0
141-
)
142+
free_cash = free_cash_override or request.trading_config.initial_capital or 0.0
143+
total_cash = total_cash_override or request.trading_config.initial_capital or 0.0
142144
constraints = Constraints(
143145
max_positions=request.trading_config.max_positions,
144146
max_leverage=request.trading_config.max_leverage,
145147
)
146148
portfolio_service = InMemoryPortfolioService(
147-
initial_capital=initial_capital,
149+
free_cash=free_cash,
150+
total_cash=total_cash,
148151
initial_positions=request.trading_config.initial_positions,
149152
trading_mode=request.exchange_config.trading_mode,
150153
market_type=request.exchange_config.market_type,

python/valuecell/agents/common/trading/portfolio/in_memory.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ class InMemoryPortfolioService(BasePortfolioService):
3636

3737
def __init__(
3838
self,
39-
initial_capital: float,
39+
free_cash: float,
40+
total_cash: float,
4041
initial_positions: Dict[str, PositionSnapshot],
4142
trading_mode: TradingMode,
4243
market_type: MarketType,
@@ -46,11 +47,16 @@ def __init__(
4647
# Store owning strategy id on the view so downstream components
4748
# always see which strategy this portfolio belongs to.
4849
self._strategy_id = strategy_id
49-
position_value = sum(
50+
net_exposure = sum(
5051
value.notional
5152
for value in initial_positions.values()
5253
if value.notional is not None
5354
)
55+
gross_exposure = sum(
56+
abs(value.notional)
57+
for value in initial_positions.values()
58+
if value.notional is not None
59+
)
5460
total_unrealized_pnl = sum(
5561
value.unrealized_pnl
5662
for value in initial_positions.values()
@@ -59,16 +65,16 @@ def __init__(
5965
self._view = PortfolioView(
6066
strategy_id=strategy_id,
6167
ts=int(datetime.now(timezone.utc).timestamp() * 1000),
62-
account_balance=initial_capital + position_value,
68+
account_balance=free_cash,
6369
positions=initial_positions,
64-
gross_exposure=position_value,
65-
net_exposure=position_value,
70+
gross_exposure=gross_exposure,
71+
net_exposure=net_exposure,
6672
constraints=constraints or None,
67-
total_value=initial_capital + position_value,
73+
total_value=total_cash + total_unrealized_pnl,
6874
total_unrealized_pnl=total_unrealized_pnl,
6975
total_realized_pnl=0.0,
70-
buying_power=initial_capital,
71-
free_cash=initial_capital,
76+
buying_power=free_cash,
77+
free_cash=free_cash,
7278
)
7379
self._trading_mode = trading_mode
7480
self._market_type = market_type

0 commit comments

Comments
 (0)