11 votos

Calcular el Promedio de Precio, Costo, (de la Onu)se dio cuenta de P&L de una posición basada en transacciones realizadas

Hemos construido un algoritmo de software de comercio y la necesidad de calcular los siguientes parámetros para cada posición en nuestra cartera.

  • Precio Medio
  • Costo
  • Se Dio Cuenta De Ganancias Y Pérdidas
  • Beneficios Y Pérdidas No Realizados

Estos valores pueden ser calculados por ir a través de antes de todos los rellenos para que la seguridad. Pero en un sistema de comercio que tiene potencialmente miles de operaciones para una sola de seguridad que esto puede llevar mucho tiempo, especialmente si este cálculo se tiene que hacer cada vez que uno necesita esos valores. Así que yo supongo que es mucho más rápido para calcular los valores a partir de los valores antes y la última llenar recibido para que la seguridad.

Cualquier ayuda es muy apreciada.

8voto

Baha Puntos 145

Hemos conseguido encontrar la respuesta a esta pregunta a nosotros mismos, pero quería compartir la respuesta, ya que podría ser relevante para otros.

El cálculo depende de qué método se utiliza para calcular el costo. No es el FIFO, LIFO y el método del coste medio, consulte: http://www.accounting-basics-for-students.com/fifo-method.html

Si FIFO o LIFO se utilizan, no hay otra manera de ir a través de cada rellenar cada vez.

Sin embargo, por el método del coste medio de uno sólo necesita los valores antes de la posición (cantidad, costo y se dio cuenta de P/L) y el más reciente de relleno (cantidad y precio).

Estos son los cálculos (en acortado código Java):

closingQty = sign(oldQty) != sign(fillQty) ? min(Math.abs(oldQty), abs(fillQty)) * sign(fillQty) : 0
openingQty = sign(oldQty) == sign(fillQty) ? fillQty : fillQty - closingQty

newQty = oldQty + fillQty
newCost = oldCost + openingQty * fillPrice + closingQty * oldCost / oldQty
newRealizedPL = oldRealizedPL + closingQty * (oldCost / oldQty - fillPrice)

El resto de los valores puede derivarse ahora:

averagePrice = cost / qty
marketValue = qty * currentPrice
unrealizedPL = cost - marketValue

Gracias a todo el mundo. Cualquier comentario?

5voto

Matthew Cole Puntos 697

El uso de Andy Flury respuesta y poco pulido se da la siguiente clase de Python para la PnL de la calculadora:

class PnLCalculator:
    def __init__(self):
        self.quantity = 0
        self.cost = 0.0
        self.market_value = 0.0
        self.r_pnl = 0.0
        self.average_price = 0.0

    def fill(self, n_pos, exec_price):
        pos_change = n_pos - self.quantity
        direction = np.sign(pos_change)
        prev_direction = np.sign(self.quantity)
        qty_closing = min(abs(self.quantity), abs(pos_change)) * direction if prev_direction != direction else 0
        qty_opening = pos_change if prev_direction == direction else pos_change - qty_closing

        new_cost = self.cost + qty_opening * exec_price
        if self.quantity != 0:
            new_cost += qty_closing * self.cost / self.quantity
            self.r_pnl += qty_closing * (self.cost / self.quantity - exec_price)

        self.quantity = n_pos
        self.cost = new_cost

    def update(self, price):
        if self.quantity != 0:
            self.average_price = self.cost / self.quantity
        else: 
            self.average_price = 0
        self.market_value = self.quantity * price
        return self.market_value - self.cost

y el uso de ella :

positions = np.array([200, 100, -100, 150, 50, 0])
exec_prices = np.array([50.0, 51.0, 49.0, 51.0, 53.0, 52.0])
pnls = []
print('Pos\t|\tR.P&L\t|\tU P&L\t|\tAvgPrc')
print('-' * 55)
pos = PnLCalculator()
pnls = []
for (p,e) in zip(positions, exec_prices):
    pos.fill(p, e)
    u_pnl = pos.update(e)
    print('%+d\t|\t%.1f\t|\t%.1f\t|\t[%.1f]' % (pos.quantity, pos.r_pnl, u_pnl, pos.average_price))
    pnls.append(u_pnl + pos.r_pnl)
print('-' * 55)
print(pnls)

Salida:

Pos     |   R.P&L   |   U P&L   |   AvgPrc
-------------------------------------------------------
+200    |   0.0     |   0.0     |   [50.0]
+100    |   100.0   |   100.0   |   [50.0]
-100    |   0.0     |   0.0     |   [49.0]
+150    |   -200.0  |   0.0     |   [51.0]
+50     |   0.0     |   100.0   |   [51.0]
+0      |   50.0    |   0.0     |   [0.0]
-------------------------------------------------------
[0.0, 200.0, 0.0, -200.0, 100.0, 50.0]

1voto

eft Puntos 254

Esta es una respuesta parcial. Se muestra cómo calcular simplemente el Total de P&L, que es la suma de las realizadas y no realizadas. Desde mi experiencia, yo en realidad no se necesita para dividirlo. Además, no calcular el Promedio de Precio, pero usted puede agregar esta funcionalidad si es necesario.

Así que, aquí está la implementación más sencilla (Java)

public class PNL {
    int position = 0;
    double money = 0.0;

    public void on_execution(double price, int quantity) {
        position += quantity;
        money -= quantity * price;
    }

    public double get_pnl(double current_price){
        double pnl = money + position * current_price;
        return pnl;
    }
}

Uso:

  • Cada vez que se produce la ejecución, llame a on_execution(), donde price es el precio de ejecución, y quantity es la ejecución de tamaño. Nota, que quantity está firmado, es decir, debe ser negativo en el caso de VENDER.

  • Siempre que necesite el total de la P&L, llame a la get_pnl() al precio actual. El precio es hasta usted para decidir. Puede ser el último precio, midprice, la posición de la liquidación de precios, etc.

Explicación: La idea aquí es muy intuitivo: cambiar dinero en la posición y viceversa. P&L es la suma de dinero y el valor de posición. Firmado quantity hace que sea consistente para cualquier dirección de comercio.

0voto

Mo. Puntos 6747

una implementación en c++ con un poco diferentes firmas:

#ifndef PNL_CALCULATOR_H
#define PNL_CALCULATOR_H

class pnl_calc{

public:

    /**
     * @brief Default Ctor. Sets everything to 0.0
     */
    pnl_calc();


    /**
     * @brief Call this method every time there is a fill.
     * @param fill_qty signed (negative for sold) amount of shares in the most recent transaction
     * @param price the price (taken or received) for the transaction 
     */
    void on_fill(const int& fill_qty, const double& price);

    /**
     * @brief Call this method every time there is a market price movement.
     * @param price the most up-to-date price of an instrument.
     */
    void on_price(const double& price);


    /**
     * @brief get the realized pnl
     * @return realized pnl
     */
    const double& get_rpnl() const;


    /**
     * @brief get the average price (never negative because cost and qty are always the same sign)
     * @return the average price
     */
    const double& get_avg_price() const;    


    /**
     * @brief get the current quantity of shares owned (or sold if negative)
     * @return the number of shares as an integer
     */
    const int& get_qty() const;


private:
    int m_qty; // this is signed 
    double m_cost; // total dollar amount invested (negative for short)
    double m_mkt_val; // total dollar amount currently worth
    double m_rlzd_pnl; // realized profit and loss
    double m_avg_price; // cost / qty
    int sgn(const double& val); 
};

#endif // PNL_CALCULATOR_H

y

#include "pnl_calculator.h"

#include <algorithm> // min

pnl_calc::pnl_calc() : m_qty(0), m_cost(0.0), m_mkt_val(0.0), m_rlzd_pnl(0.0), m_avg_price(0.0)
{    
}


void pnl_calc::on_fill(const int& fill_qty, const double& price)
{
    int direction = sgn(fill_qty);
    int prev_direction = sgn(m_qty); 


    int qty_opening, qty_closing;
    if(prev_direction == direction){ 
        qty_closing = 0;
        qty_opening = fill_qty; 
    }else{  
        qty_closing = std::min(std::abs(m_qty), std::abs(fill_qty)) * direction;  // first case is reversal, second is a partial closeout
        qty_opening = fill_qty - qty_closing;
    }

    double new_cost = m_cost + qty_opening*price;
    if(m_qty != 0){
        new_cost += qty_closing*m_cost/m_qty;
        m_rlzd_pnl += qty_closing*(m_cost/m_qty - price);
    }

    m_qty += fill_qty;
    m_cost = new_cost;    

    if(m_qty != 0){
        m_avg_price = m_cost / m_qty;
    }else{
        m_avg_price = 0.0;
    }

}


void pnl_calc::on_price(const double& price)
{
    m_mkt_val = m_qty * price;
}


int pnl_calc::sgn(const double& val) 
{
    return (0.0 < val) - (val < 0.0);
}


const double& pnl_calc::get_rpnl() const
{
    return m_rlzd_pnl;
}


const double& pnl_calc::get_avg_price() const
{
    return m_avg_price;
}


const int& pnl_calc::get_qty() const
{
    return m_qty;
}

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