DDL schemas for Trading Platform: - User management - Authentication - Payments - Education - ML predictions - Trading data Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
97 lines
3.2 KiB
PL/PgSQL
97 lines
3.2 KiB
PL/PgSQL
-- ============================================================================
|
|
-- Schema: trading
|
|
-- Function: calculate_position_pnl
|
|
-- Description: Calcula el PnL (realized y unrealized) de una posición
|
|
-- Parameters:
|
|
-- p_position_id: ID de la posición
|
|
-- p_current_price: Precio actual del mercado (para unrealized PnL)
|
|
-- Returns: JSONB con realized_pnl, unrealized_pnl, pnl_percentage
|
|
-- ============================================================================
|
|
|
|
CREATE OR REPLACE FUNCTION trading.calculate_position_pnl(
|
|
p_position_id UUID,
|
|
p_current_price DECIMAL(20,8) DEFAULT NULL
|
|
)
|
|
RETURNS JSONB
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
DECLARE
|
|
v_position RECORD;
|
|
v_realized_pnl DECIMAL(20,8) := 0;
|
|
v_unrealized_pnl DECIMAL(20,8) := 0;
|
|
v_pnl_percentage DECIMAL(10,4) := 0;
|
|
v_total_commission DECIMAL(20,8) := 0;
|
|
v_current_value DECIMAL(20,8);
|
|
BEGIN
|
|
-- Obtener datos de la posición
|
|
SELECT
|
|
p.position_side,
|
|
p.status,
|
|
p.entry_price,
|
|
p.entry_quantity,
|
|
p.entry_value,
|
|
p.entry_commission,
|
|
p.exit_price,
|
|
p.exit_quantity,
|
|
p.exit_value,
|
|
p.exit_commission
|
|
INTO v_position
|
|
FROM trading.positions p
|
|
WHERE p.id = p_position_id;
|
|
|
|
IF NOT FOUND THEN
|
|
RAISE EXCEPTION 'Position % not found', p_position_id;
|
|
END IF;
|
|
|
|
-- Calcular comisiones totales
|
|
v_total_commission := COALESCE(v_position.entry_commission, 0) + COALESCE(v_position.exit_commission, 0);
|
|
|
|
-- Calcular PnL según el estado
|
|
IF v_position.status = 'closed' OR v_position.status = 'liquidated' THEN
|
|
-- Posición cerrada: calcular realized PnL
|
|
IF v_position.position_side = 'buy' THEN
|
|
-- Long position: profit = (exit_price - entry_price) * quantity - commissions
|
|
v_realized_pnl := (v_position.exit_value - v_position.entry_value) - v_total_commission;
|
|
ELSE
|
|
-- Short position: profit = (entry_price - exit_price) * quantity - commissions
|
|
v_realized_pnl := (v_position.entry_value - v_position.exit_value) - v_total_commission;
|
|
END IF;
|
|
|
|
-- Calcular porcentaje
|
|
IF v_position.entry_value > 0 THEN
|
|
v_pnl_percentage := (v_realized_pnl / v_position.entry_value) * 100;
|
|
END IF;
|
|
|
|
ELSIF v_position.status = 'open' AND p_current_price IS NOT NULL THEN
|
|
-- Posición abierta: calcular unrealized PnL
|
|
v_current_value := p_current_price * v_position.entry_quantity;
|
|
|
|
IF v_position.position_side = 'buy' THEN
|
|
-- Long position
|
|
v_unrealized_pnl := (v_current_value - v_position.entry_value) - v_position.entry_commission;
|
|
ELSE
|
|
-- Short position
|
|
v_unrealized_pnl := (v_position.entry_value - v_current_value) - v_position.entry_commission;
|
|
END IF;
|
|
|
|
-- Calcular porcentaje
|
|
IF v_position.entry_value > 0 THEN
|
|
v_pnl_percentage := (v_unrealized_pnl / v_position.entry_value) * 100;
|
|
END IF;
|
|
END IF;
|
|
|
|
-- Retornar resultado
|
|
RETURN jsonb_build_object(
|
|
'position_id', p_position_id,
|
|
'status', v_position.status,
|
|
'realized_pnl', v_realized_pnl,
|
|
'unrealized_pnl', v_unrealized_pnl,
|
|
'pnl_percentage', v_pnl_percentage,
|
|
'total_commission', v_total_commission
|
|
);
|
|
END;
|
|
$$;
|
|
|
|
-- Comentarios
|
|
COMMENT ON FUNCTION trading.calculate_position_pnl IS 'Calcula el PnL realizado y no realizado de una posición';
|