2 votos

Operaciones por pares basadas en la cointegración - línea de renta variable

Estoy preparando un proyecto en mi Uni donde tengo que hacer un simple comercio de pares estrategia que utiliza la cointegración entre dos valores.

Estoy atascado en el cálculo de la línea de equidad. He preparado las señales de apertura y cierre, pero todavía tengo que preparar un línea de equidad de la parcela pero no sé cómo calcularlo.

Hay algunos detalles:

-Posición larga en acciones infravaloradas y corta en las sobrevaloradas

-se permite la venta en corto sin límites, con el depósito del 100% del valor de la venta en corto

-al abrir la posición, asumimos partes iguales de posiciones cortas y largas

- abrir/cerrar Las señales están definidas por el precio de cierre Las posiciones son abierto/cerrado al día siguiente precio abierto

- tasa de transacción son 0,1% del valor de la posición (a la apertura y al cierre)

2voto

Zsolt Ringhofer Puntos 31

Sí, eso puede ser realmente sofisticado incluso utilizando herramientas tan bonitas como pandas. Pero la idea básica es encontrar entradas y salidas de posiciones para derivar el flujo de caja.

Aquí está mi código para derivar todas esas cosas de las señales generadas (en mi backtester las señales son fracciones de 2 acciones en cartera para cada momento). Espero haber encontrado todos los errores aquí, pero no hay garantías. Total_invertido se utiliza para calcular el número total de acciones en la cartera utilizando sólo el capital inicial.

En realidad, este código es parte de mi motor de backtest que voy a abrir en unos meses. También se ocupa de los spreads y las comisiones fijas, por lo que puede omitir esta parte. Será necesario adaptarlo a tus condiciones, pero espero que te sirva de ayuda.

También puede consultar artículos de Mike Halls-Moore . Este sitio me ha ayudado mucho.

def get_portfolio(self, signals, prices):
    time_index = prices.index
    end = time_index[-1]
    # Assets prices
    x_prices = prices[self.sym1]
    y_prices = prices[self.sym2]
    # Assets weights in portfolio
    x_weights = signals.map(lambda sig:sig[self.sym1])
    y_weights = signals.map(lambda sig:sig[self.sym2])
    # Total number of invested shares
    total_invested = pd.Series(index = signals.index)
    # Need trade enters to calculate portfolio size
    enter_points = x_weights.diff().fillna(0)!=0
    # Index magic here:
    # We need to delete position exits, we suppose there are separate enters/exits
    enter_points[enter_points[enter_points].index[1::2]] = False
    # capital = w₁⋅total⋅p₁ + w₂⋅total⋅p₂ (cover position)
    total_invested[enter_points] = (self.initial_capital
        /(x_weights.abs()[enter_points]*x_prices[enter_points]
        + y_weights.abs()[enter_points]*y_prices[enter_points]))
    # Zero for right initial open and final close
    total_invested.iloc[0] = 0; total_invested.iloc[-1] = 0;
    total_invested.fillna(method='ffill', inplace=True)
    # Positions rounded to lot sizes
    x_positions = (total_invested*x_weights//self.lot1*self.lot1).fillna(0)
    y_positions = (total_invested*y_weights//self.lot2*self.lot2).fillna(0)
    long_pos = x_positions.copy(); long_pos[long_pos<0] = 0
    short_pos = x_positions.copy(); short_pos[short_pos>0] = 0
    x_pos_diff = x_positions.diff().fillna(0)
    y_pos_diff = y_positions.diff().fillna(0)

    # Tribute to the market-makers: spread
    # Binary divide because we count twice: enter & exit
    tribute = (abs(x_pos_diff)*self.spread1 + abs(y_pos_diff)*self.spread2)/2
    # Cashflow & Turnover: not the same!
    cashflow = -x_pos_diff*x_prices - y_pos_diff*y_prices
    turnover = abs(x_pos_diff)*x_prices + abs(y_pos_diff)*y_prices
    # Commission from turnover
    commission = turnover * self.commission
    commission[cashflow!=0] += self.fixed_commission
    portfolio = pd.DataFrame(index=time_index, columns=['EQ','holdings',
        'cash','cashflow','long_trades','short_trades',
        'x_positions','y_positions'])
    # Value of shares
    portfolio['holdings'] = x_positions*x_prices + y_positions*y_prices
    # Value of cash, paid commission on each transaction
    portfolio['cash'] = self.initial_capital + (cashflow
        - commission - tribute).cumsum()
    # Equity is the sum of both
    portfolio['EQ'] = portfolio['cash'] + portfolio['holdings']
    portfolio['turnover'] = turnover

    # Time points of trades
    portfolio['long_trades'] = long_pos.diff().fillna(0)
    portfolio['short_trades'] = short_pos.diff().fillna(0)

    portfolio['x_positions'] = x_positions
    portfolio['y_positions'] = y_positions
    return portfolio

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