fix(trading_engine): deduct execution value from account cash balance

The old code computed `_execution_value = quantity * price` but
discarded it (underscore prefix).  Only commission was subtracted,
so the account cash balance never reflected the cost of buying or
the proceeds from selling.

Now `update_from_execution` matches on the new `execution.side` field:
- Buy  → cash -= execution_value + commission
- Sell → cash += execution_value − commission

Test assertions updated to expect the corrected balances.

Addresses audit item H2 (account never deducting trade value).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jgrusewski
2026-02-23 20:47:04 +01:00
parent 3cbf643b4d
commit 2f83e57826

View File

@@ -111,21 +111,23 @@ impl AccountManager {
.ok_or("Demo account not found")?;
// Convert Quantity and Price to Decimal for calculation
let quantity_decimal = execution.executed_quantity;
let price_decimal = execution.execution_price;
let _execution_value = quantity_decimal * price_decimal;
let execution_value = execution.executed_quantity * execution.execution_price;
let commission = execution.commission;
// Update cash balance based on execution
// Note: This is simplified - in reality you'd need to track whether this
// is opening or closing a position, and handle margin accounts properly
// Update cash balance based on execution side
match execution.side {
OrderSide::Buy => {
// Buying: cash decreases by execution value + commission
account.cash_balance -= execution_value + commission;
}
OrderSide::Sell => {
// Selling: cash increases by execution value, minus commission
account.cash_balance += execution_value - commission;
}
}
// For now, assume all executions affect cash balance
account.cash_balance -= commission; // Always subtract commission
// Update total value (would normally be calculated from positions + cash)
// For now, just subtract commission from total value
account.total_value -= commission;
// Update total value from cash (position values tracked separately)
account.total_value = account.cash_balance;
info!(
"Account updated from execution {}: commission {}, new cash balance {}",
@@ -502,6 +504,7 @@ mod tests {
let execution = ExecutionResult {
order_id: "exec-001".to_string().into(),
symbol: "BTCUSD".to_string(),
side: OrderSide::Buy,
executed_quantity: Decimal::from(1),
execution_price: Decimal::from(50000),
execution_time: Utc::now(),
@@ -512,22 +515,20 @@ mod tests {
let result = manager.update_from_execution(&execution).await;
assert!(result.is_ok());
// Verify cash balance was reduced by commission only (10)
// Verify cash balance was reduced by execution value + commission
// Buy: cash -= (1 * 50000) + 10 = 50010
let account = manager
.get_account_info("DEMO_ACCOUNT")
.await
.expect("Demo account should exist");
// Cash balance should be reduced by commission
// Cash balance: 50000 - 50000 - 10 = -10
assert_eq!(
account.cash_balance,
Decimal::from(50000) - Decimal::from(10)
);
// Total value should also be reduced by commission
assert_eq!(
account.total_value,
Decimal::from(100000) - Decimal::from(10)
Decimal::from(50000) - Decimal::from(50000) - Decimal::from(10)
);
// Total value tracks cash balance
assert_eq!(account.total_value, account.cash_balance);
}
#[tokio::test]