3 votos

Forma robusta de calcular las pérdidas y ganancias para la negociación de acciones/futuros

He implementado una clase en C# que calculará las pérdidas y ganancias en función de esta descripción de TT. Sin embargo, me preocupa que dé resultados diferentes para los mismos rellenos, si se aplican los cálculos de "descarga de rellenos" frente a si simplemente se añaden rellenos (ejemplo de abajo).

¿Existe un recurso de referencia claro para el cálculo de las pérdidas y ganancias? Google me ha fallado significativamente en este caso. Incluyo el código en caso de que esto puede dar una idea de un error.

public sealed class ProfitLoss
{
    public double Realized { get; private set; }

    public int Net { get; private set; }

    public double AverageOpenPrice { get; private set; }

    public ProfitLoss()
    {

    }

    public ProfitLoss(IEnumerable<Tuple<int, double>> initial)
    {
        int buyQuantity = 0, sellQuantity = 0;
        double averageBuyPrice = 0, averageSellPrice = 0;
        foreach (var fill in initial)
        {
            if (fill.Item1 > 0)
            {
                buyQuantity += fill.Item1;
                averageBuyPrice += fill.Item1 * fill.Item2;
            }
            else if (fill.Item1 < 0)
            {
                int absQuantity = Math.Abs(fill.Item1);
                sellQuantity += absQuantity;
                averageSellPrice += absQuantity * fill.Item2;
            }
        }

        if (buyQuantity > 0)
            averageBuyPrice /= buyQuantity;
        if (sellQuantity > 0)
            averageSellPrice /= sellQuantity;

        Net = buyQuantity - sellQuantity;
        AverageOpenPrice = Net > 0 ? averageBuyPrice : averageSellPrice;
        Realized = (averageSellPrice - averageBuyPrice) * Math.Min(buyQuantity, sellQuantity);
    }

    public void AddFill(int quantity, double price)
    {
        if (quantity == 0)
            throw new ArgumentOutOfRangeException(nameof(quantity), "Quantity must be non-zero.");

        if (Math.Sign(Net) != Math.Sign(quantity))
        {
            int absNet = Math.Abs(Net);
            int absQuantity = Math.Abs(quantity);

            if (absNet == absQuantity) // flat
            {
                Realized += (price - AverageOpenPrice) * Net;
                AverageOpenPrice = 0;
            }
            else if (absNet > absQuantity) // decrease
            {
                Realized += (price - AverageOpenPrice) * -quantity;
            }
            else // reverse
            {
                Realized += (price - AverageOpenPrice) * Net;
                AverageOpenPrice = price;
            }
        }
        else // increase position
        {
            AverageOpenPrice = (Net * AverageOpenPrice + quantity * price) / (Net + quantity);
        }

        Net += quantity;
    }

    public double FloatingForTheoriticalExit(double exitPrice)
    {
        return (exitPrice - AverageOpenPrice) * Net;
    }
}

Ejemplo de diferencia de cálculo:

new ProfitLoss(new[] {
    Tuple.Create(12, 100.0),
    Tuple.Create(17, 99.0),
    Tuple.Create(-9, 101.0),
    Tuple.Create(-4, 105.0),
    Tuple.Create(3, 103.0)
}).Dump();

Rendimientos:

Realized 32.2499999999999 
Net 19 
AverageOpenPrice 99.75 

Pero

var calc = new ProfitLoss();
calc.AddFill(12, 100);
calc.AddFill(17, 99);
calc.AddFill(-9, 101);
calc.AddFill(-4, 105);
calc.AddFill(3, 103);
calc.Dump();

Rendimientos:

Realized 36.6206896551725 
Net 19 
AverageOpenPrice 99.9800362976407

1voto

Zac Puntos 11

Tras la sugerencia de @AlexC he probado a añadir rellenos para aplanar el posicionamiento de la red y los dos cálculos devuelven efectivamente el mismo resultado en términos de PnL realizado:

new ProfitLoss(new[] {
    new Fill(12, 100.0),
    new Fill(17, 99.0),
    new Fill(-9, 101.0),
    new Fill(-4, 105.0),
    new Fill(3, 103.0),
    new Fill(-19, 100)
}).Dump();

var calc = new ProfitLoss();
calc.AddFill(12, 100);
calc.AddFill(17, 99);
calc.AddFill(-9, 101);
calc.AddFill(-4, 105);
calc.AddFill(3, 103);
calc.AddFill(-19, 100);
calc.Dump();

Ambas cosas dan un PnL realizado de 37.

Finanhelp.com

FinanHelp es una comunidad para personas con conocimientos de economía y finanzas, o quiere aprender. Puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X