"""
Trading-related calculations for position sizing, risk management, and price calculations.
Author: @TexasCoding
Date: 2025-08-02
Overview:
Provides trading-related calculations for position sizing, risk management,
and price calculations. Includes tick value calculations, position sizing
based on risk management, price rounding to tick sizes, and risk/reward
ratio calculations for trading strategy development.
Key Features:
- Tick value calculations for different instruments
- Position sizing based on risk management principles
- Price rounding to valid tick sizes
- Risk/reward ratio calculations
- Position value calculations
- Comprehensive risk management tools
Trading Calculations:
- Tick value and price movement calculations
- Position sizing with risk management
- Price alignment to tick size requirements
- Risk/reward ratio analysis
- Position value and exposure calculations
- Risk management and sizing optimization
Example Usage:
```python
from project_x_py.utils import (
calculate_tick_value,
calculate_position_sizing,
round_to_tick_size,
calculate_risk_reward_ratio,
calculate_position_value,
)
# Calculate tick value for price movement
tick_value = calculate_tick_value(0.5, 0.1, 1.0) # 5 ticks
print(f"Tick value: ${tick_value}")
# Calculate position sizing based on risk
sizing = calculate_position_sizing(50000, 0.02, 2050, 2040, 1.0)
print(f"Position size: {sizing['position_size']} contracts")
print(f"Risk per trade: {sizing['actual_risk_percent']:.2%}")
# Round price to valid tick size
price = round_to_tick_size(2050.37, 0.1)
print(f"Rounded price: {price}")
# Calculate risk/reward ratio
ratio = calculate_risk_reward_ratio(2050, 2045, 2065)
print(f"Risk/Reward ratio: {ratio:.2f}")
# Calculate position value
value = calculate_position_value(5, 2050.0, 1.0, 0.1)
print(f"Position value: ${value:,.2f}")
```
Risk Management Features:
- Position sizing based on account balance and risk tolerance
- Risk per trade calculation and validation
- Price risk and dollar risk calculations
- Actual vs. target risk percentage tracking
- Risk management optimization and validation
- Comprehensive risk analysis and reporting
Tick Value Calculations:
- Dollar value of price movements
- Tick size validation and error handling
- Multi-instrument tick value support
- Precision calculations for accurate pricing
- Error handling for invalid inputs
Position Sizing:
- Risk-based position sizing algorithms
- Account balance and risk tolerance integration
- Stop loss and entry price calculations
- Position size optimization and validation
- Risk percentage tracking and reporting
- Comprehensive sizing analysis
Performance Characteristics:
- Fast calculation algorithms for real-time trading
- Memory-efficient calculations
- Type-safe operations with proper validation
- Optimized for high-frequency trading scenarios
- Comprehensive error handling and validation
See Also:
- `utils.portfolio_analytics`: Portfolio analysis and metrics
- `utils.pattern_detection`: Pattern detection for trading signals
- `utils.data_utils`: Data processing and analysis
"""
from typing import Any
[docs]
def calculate_tick_value(
price_change: float, tick_size: float, tick_value: float
) -> float:
"""
Calculate dollar value of a price change.
Args:
price_change: Price difference
tick_size: Minimum price movement
tick_value: Dollar value per tick
Returns:
float: Dollar value of the price change
Example:
>>> # MGC moves 5 ticks
>>> calculate_tick_value(0.5, 0.1, 1.0)
5.0
"""
# Validate inputs
if tick_size <= 0:
raise ValueError(f"tick_size must be positive, got {tick_size}")
if tick_value < 0:
raise ValueError(f"tick_value cannot be negative, got {tick_value}")
if not isinstance(price_change, int | float):
raise TypeError(f"price_change must be numeric, got {type(price_change)}")
num_ticks = abs(price_change) / tick_size
return num_ticks * tick_value
[docs]
def calculate_position_value(
size: int, price: float, tick_value: float, tick_size: float
) -> float:
"""
Calculate total dollar value of a position.
Args:
size: Number of contracts
price: Current price
tick_value: Dollar value per tick
tick_size: Minimum price movement
Returns:
float: Total position value in dollars
Example:
>>> # 5 MGC contracts at $2050
>>> calculate_position_value(5, 2050.0, 1.0, 0.1)
102500.0
"""
# Validate inputs
if tick_size <= 0:
raise ValueError(f"tick_size must be positive, got {tick_size}")
if tick_value < 0:
raise ValueError(f"tick_value cannot be negative, got {tick_value}")
if price < 0:
raise ValueError(f"price cannot be negative, got {price}")
if not isinstance(size, int):
raise TypeError(f"size must be an integer, got {type(size)}")
ticks_per_point = 1.0 / tick_size
value_per_point = ticks_per_point * tick_value
return abs(size) * price * value_per_point
[docs]
def round_to_tick_size(price: float, tick_size: float) -> float:
"""
Round price to nearest valid tick.
Args:
price: Price to round
tick_size: Minimum price movement
Returns:
float: Price rounded to nearest tick
Raises:
ValueError: If tick_size is not positive or price is negative
Example:
>>> round_to_tick_size(2050.37, 0.1)
2050.4
"""
# Validate inputs
if tick_size <= 0:
raise ValueError(f"tick_size must be positive, got {tick_size}")
if price < 0:
raise ValueError(f"price cannot be negative, got {price}")
return round(price / tick_size) * tick_size
[docs]
def calculate_risk_reward_ratio(
entry_price: float, stop_price: float, target_price: float
) -> float:
"""
Calculate risk/reward ratio for a trade setup.
Args:
entry_price: Entry price
stop_price: Stop loss price
target_price: Profit target price
Returns:
float: Risk/reward ratio (reward / risk)
Raises:
ValueError: If prices are invalid (e.g., stop/target inversion)
Example:
>>> # Long trade: entry=2050, stop=2045, target=2065
>>> calculate_risk_reward_ratio(2050, 2045, 2065)
3.0
"""
if entry_price == stop_price:
raise ValueError("Entry price and stop price cannot be equal")
risk = abs(entry_price - stop_price)
reward = abs(target_price - entry_price)
is_long = stop_price < entry_price
if is_long and target_price <= entry_price:
raise ValueError("For long positions, target must be above entry")
elif not is_long and target_price >= entry_price:
raise ValueError("For short positions, target must be below entry")
if risk <= 0:
return 0.0
return reward / risk
[docs]
def calculate_position_sizing(
account_balance: float,
risk_per_trade: float,
entry_price: float,
stop_loss_price: float,
tick_value: float = 1.0,
) -> dict[str, Any]:
"""
Calculate optimal position size based on risk management.
Args:
account_balance: Current account balance
risk_per_trade: Risk per trade as decimal (e.g., 0.02 for 2%)
entry_price: Entry price for the trade
stop_loss_price: Stop loss price
tick_value: Dollar value per tick
Returns:
Dict with position sizing information
Example:
>>> sizing = calculate_position_sizing(50000, 0.02, 2050, 2040, 1.0)
>>> print(f"Position size: {sizing['position_size']} contracts")
"""
# Validate inputs
if account_balance <= 0:
raise ValueError(f"account_balance must be positive, got {account_balance}")
if not 0 < risk_per_trade <= 1:
raise ValueError(
f"risk_per_trade must be between 0 and 1, got {risk_per_trade}"
)
if entry_price <= 0:
raise ValueError(f"entry_price must be positive, got {entry_price}")
if stop_loss_price <= 0:
raise ValueError(f"stop_loss_price must be positive, got {stop_loss_price}")
if tick_value <= 0:
raise ValueError(f"tick_value must be positive, got {tick_value}")
try:
# Calculate risk per share/contract
price_risk = abs(entry_price - stop_loss_price)
if price_risk == 0:
return {"error": "No price risk (entry equals stop loss)"}
# Calculate dollar risk
dollar_risk_per_contract = price_risk * tick_value
# Calculate maximum dollar risk for this trade
max_dollar_risk = account_balance * risk_per_trade
# Calculate position size
position_size = max_dollar_risk / dollar_risk_per_contract
# Round down to whole contracts
position_size = int(position_size)
# Calculate actual risk
actual_dollar_risk = position_size * dollar_risk_per_contract
actual_risk_percent = actual_dollar_risk / account_balance
return {
"position_size": position_size,
"price_risk": price_risk,
"dollar_risk_per_contract": dollar_risk_per_contract,
"max_dollar_risk": max_dollar_risk,
"actual_dollar_risk": actual_dollar_risk,
"actual_risk_percent": actual_risk_percent,
"risk_reward_ratio": None, # Can be calculated if target provided
}
except Exception as e:
return {"error": str(e)}