diff --git a/src/main.py b/src/main.py
index 7257188..c01e5f1 100644
--- a/src/main.py
+++ b/src/main.py
@@ -624,11 +624,21 @@ async def run(settings: Settings) -> None:
# Get trading status
trading_status = "Active" if pause_trading.is_set() else "Paused"
- # Get current P&L from risk manager
+ # Calculate P&L from balance data
try:
balance = await broker.get_balance()
- current_pnl = risk.calculate_pnl(balance)
- pnl_str = f"{current_pnl:+.2f}%"
+ output2 = balance.get("output2", [{}])
+ if output2:
+ total_eval = safe_float(output2[0].get("tot_evlu_amt", "0"))
+ purchase_total = safe_float(output2[0].get("pchs_amt_smtl_amt", "0"))
+ current_pnl = (
+ ((total_eval - purchase_total) / purchase_total * 100)
+ if purchase_total > 0
+ else 0.0
+ )
+ pnl_str = f"{current_pnl:+.2f}%"
+ else:
+ pnl_str = "N/A"
except Exception as exc:
logger.warning("Failed to get P&L: %s", exc)
pnl_str = "N/A"
@@ -642,7 +652,7 @@ async def run(settings: Settings) -> None:
f"Markets: {markets_str}\n"
f"Trading: {trading_status}\n\n"
f"Current P&L: {pnl_str}\n"
- f"Circuit Breaker: {risk.circuit_breaker_threshold:.1f}%"
+ f"Circuit Breaker: {risk._cb_threshold:.1f}%"
)
await telegram.send_message(message)
@@ -653,52 +663,40 @@ async def run(settings: Settings) -> None:
)
async def handle_positions() -> None:
- """Handle /positions command - show current holdings."""
+ """Handle /positions command - show account summary."""
try:
# Get account balance
balance = await broker.get_balance()
+ output2 = balance.get("output2", [{}])
- # Check if there are any positions
- if not balance.stocks:
+ if not output2:
await telegram.send_message(
- "š¼ Current Holdings\n\n"
- "No positions currently held."
+ "š¼ Account Summary\n\n"
+ "No balance information available."
)
return
- # Group positions by market (domestic vs overseas)
- domestic_positions = []
- overseas_positions = []
+ # Extract account-level data
+ total_eval = safe_float(output2[0].get("tot_evlu_amt", "0"))
+ total_cash = safe_float(output2[0].get("dnca_tot_amt", "0"))
+ purchase_total = safe_float(output2[0].get("pchs_amt_smtl_amt", "0"))
- for stock in balance.stocks:
- position_str = (
- f"⢠{stock.code}: {stock.quantity} shares @ "
- f"{stock.avg_price:,.0f}"
- )
-
- # Simple heuristic: if code is 6 digits, it's domestic (Korea)
- if len(stock.code) == 6 and stock.code.isdigit():
- domestic_positions.append(position_str)
- else:
- overseas_positions.append(position_str)
-
- # Build message
- message_parts = ["š¼ Current Holdings\n"]
-
- if domestic_positions:
- message_parts.append("\nš°š· Korea")
- message_parts.extend(domestic_positions)
-
- if overseas_positions:
- message_parts.append("\nšŗšø Overseas")
- message_parts.extend(overseas_positions)
-
- # Add total cash
- message_parts.append(
- f"\nCash: ā©{balance.total_cash:,.0f}"
+ # Calculate P&L
+ pnl_pct = (
+ ((total_eval - purchase_total) / purchase_total * 100)
+ if purchase_total > 0
+ else 0.0
)
+ pnl_sign = "+" if pnl_pct >= 0 else ""
- message = "\n".join(message_parts)
+ message = (
+ "š¼ Account Summary\n\n"
+ f"Total Evaluation: ā©{total_eval:,.0f}\n"
+ f"Available Cash: ā©{total_cash:,.0f}\n"
+ f"Purchase Total: ā©{purchase_total:,.0f}\n"
+ f"P&L: {pnl_sign}{pnl_pct:.2f}%\n\n"
+ "Note: Individual position details require API enhancement"
+ )
await telegram.send_message(message)
except Exception as exc:
diff --git a/tests/test_telegram_commands.py b/tests/test_telegram_commands.py
index 1b78a6e..c1ef067 100644
--- a/tests/test_telegram_commands.py
+++ b/tests/test_telegram_commands.py
@@ -549,7 +549,7 @@ class TestStatusCommands:
@pytest.mark.asyncio
async def test_positions_command_shows_holdings(self) -> None:
- """Positions command displays current holdings."""
+ """Positions command displays account summary."""
client = TelegramClient(bot_token="123:abc", chat_id="456", enabled=True)
handler = TelegramCommandHandler(client)
@@ -561,12 +561,12 @@ class TestStatusCommands:
async def mock_positions() -> None:
"""Mock /positions handler."""
message = (
- "š¼ Current Holdings\n"
- "\nš°š· Korea\n"
- "⢠005930: 10 shares @ 70,000\n"
- "\nšŗšø Overseas\n"
- "⢠AAPL: 15 shares @ 175\n"
- "\nCash: ā©5,000,000"
+ "š¼ Account Summary\n\n"
+ "Total Evaluation: ā©10,500,000\n"
+ "Available Cash: ā©5,000,000\n"
+ "Purchase Total: ā©10,000,000\n"
+ "P&L: +5.00%\n\n"
+ "Note: Individual position details require API enhancement"
)
await client.send_message(message)
@@ -586,8 +586,9 @@ class TestStatusCommands:
# Verify message was sent
assert mock_post.call_count == 1
payload = mock_post.call_args.kwargs["json"]
- assert "Current Holdings" in payload["text"]
- assert "shares" in payload["text"]
+ assert "Account Summary" in payload["text"]
+ assert "Total Evaluation" in payload["text"]
+ assert "P&L" in payload["text"]
@pytest.mark.asyncio
async def test_positions_command_empty_holdings(self) -> None:
@@ -603,8 +604,8 @@ class TestStatusCommands:
async def mock_positions_empty() -> None:
"""Mock /positions handler with no positions."""
message = (
- "š¼ Current Holdings\n\n"
- "No positions currently held."
+ "š¼ Account Summary\n\n"
+ "No balance information available."
)
await client.send_message(message)
@@ -623,7 +624,7 @@ class TestStatusCommands:
# Verify message was sent
payload = mock_post.call_args.kwargs["json"]
- assert "No positions" in payload["text"]
+ assert "No balance information available" in payload["text"]
@pytest.mark.asyncio
async def test_positions_command_error_handling(self) -> None: