Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Position Management

Functions for managing and analyzing trading and lending positions.

Position Size

Calculate appropriate position size based on risk parameters:

#![allow(unused)]
fn main() {
use risk_metrics::{position_size, Decimal};

let account_balance = Decimal::from(100000i64);
let risk_per_trade = Decimal::new(2, 2);  // 2% risk
let stop_loss_pct = Decimal::new(5, 2);   // 5% stop loss

let size = position_size(account_balance, risk_per_trade, stop_loss_pct)?;
// size = $40,000 (2% risk / 5% stop = 40% of account)
}

Leverage Calculation

Determine effective leverage of a position:

#![allow(unused)]
fn main() {
use risk_metrics::{effective_leverage, Decimal};

let position_value = Decimal::from(50000i64);
let collateral = Decimal::from(10000i64);

let leverage = effective_leverage(position_value, collateral)?;
// leverage = 5x
}

Margin Requirements

Calculate required margin for a leveraged position:

#![allow(unused)]
fn main() {
use risk_metrics::{required_margin, Decimal};

let position_size = Decimal::from(100000i64);
let leverage = Decimal::from(10i64);

let margin = required_margin(position_size, leverage)?;
// margin = $10,000
}

Profit and Loss

Unrealized PnL

#![allow(unused)]
fn main() {
use risk_metrics::{unrealized_pnl, Decimal};

let entry_price = Decimal::from(2000i64);
let current_price = Decimal::from(2150i64);
let position_size = Decimal::from(5i64);  // 5 ETH
let is_long = true;

let pnl = unrealized_pnl(entry_price, current_price, position_size, is_long)?;
// pnl = +$750
}

Return on Investment

#![allow(unused)]
fn main() {
use risk_metrics::{position_roi, Decimal};

let entry_value = Decimal::from(10000i64);
let current_value = Decimal::from(12500i64);

let roi = position_roi(entry_value, current_value)?;
// roi = 25%
}

Risk-Adjusted Returns

Sharpe Ratio Components

#![allow(unused)]
fn main() {
use risk_metrics::{excess_return, Decimal};

let portfolio_return = Decimal::new(12, 2);  // 12%
let risk_free_rate = Decimal::new(4, 2);     // 4%

let excess = excess_return(portfolio_return, risk_free_rate)?;
// excess = 8%
}

Practical Examples

Position Sizing with Kelly Criterion

#![allow(unused)]
fn main() {
use risk_metrics::Decimal;

fn kelly_fraction(
    win_probability: Decimal,
    win_loss_ratio: Decimal,
) -> Result<Decimal, ArithmeticError> {
    // Kelly % = W - (1-W)/R
    // where W = win probability, R = win/loss ratio
    let loss_probability = Decimal::ONE.checked_sub(win_probability)?;
    let second_term = loss_probability.checked_div(win_loss_ratio)?;
    win_probability.checked_sub(second_term)
}

let win_rate = Decimal::new(55, 2);    // 55% win rate
let win_loss = Decimal::new(15, 1);    // 1.5:1 win/loss ratio

let kelly = kelly_fraction(win_rate, win_loss)?;
// Use half-Kelly for safety: kelly / 2
}

Portfolio Position Limits

#![allow(unused)]
fn main() {
fn validate_position(
    new_position: Decimal,
    portfolio_value: Decimal,
    max_concentration: Decimal,  // e.g., 10%
) -> bool {
    let concentration = new_position
        .checked_div(portfolio_value)
        .unwrap_or(Decimal::MAX);

    concentration <= max_concentration
}
}

Liquidation-Safe Position

#![allow(unused)]
fn main() {
use risk_metrics::{max_borrowable, health_factor, Decimal};

fn safe_position_size(
    available_collateral: Decimal,
    threshold: Decimal,
    target_hf: Decimal,
    price_buffer: Decimal,  // e.g., 20% buffer for volatility
) -> Result<Decimal, ArithmeticError> {
    // Reduce effective collateral by price buffer
    let buffered_collateral = available_collateral
        .checked_mul(Decimal::ONE.checked_sub(price_buffer)?)?;

    max_borrowable(buffered_collateral, threshold, target_hf)
}
}

Break-Even Analysis

#![allow(unused)]
fn main() {
fn break_even_price(
    entry_price: Decimal,
    position_size: Decimal,
    fees: Decimal,
    is_long: bool,
) -> Result<Decimal, ArithmeticError> {
    let fee_per_unit = fees.checked_div(position_size)?;

    if is_long {
        entry_price.checked_add(fee_per_unit)
    } else {
        entry_price.checked_sub(fee_per_unit)
    }
}
}

Position Tracking

#![allow(unused)]
fn main() {
struct Position {
    asset: String,
    entry_price: Decimal,
    size: Decimal,
    is_long: bool,
    stop_loss: Option<Decimal>,
    take_profit: Option<Decimal>,
}

impl Position {
    fn value_at(&self, price: Decimal) -> Result<Decimal, ArithmeticError> {
        self.size.checked_mul(price)
    }

    fn pnl_at(&self, price: Decimal) -> Result<Decimal, ArithmeticError> {
        let diff = if self.is_long {
            price.checked_sub(self.entry_price)?
        } else {
            self.entry_price.checked_sub(price)?
        };
        diff.checked_mul(self.size)
    }

    fn should_close(&self, price: Decimal) -> bool {
        if let Some(sl) = self.stop_loss {
            if (self.is_long && price <= sl) || (!self.is_long && price >= sl) {
                return true;
            }
        }
        if let Some(tp) = self.take_profit {
            if (self.is_long && price >= tp) || (!self.is_long && price <= tp) {
                return true;
            }
        }
        false
    }
}
}