Векторизованное вычисление возвратов с позиций и серий бид-аск - PullRequest
1 голос
/ 15 марта 2020

У меня есть две серии (bids и asks) и список позиций. Все они имеют форму (T, S).

В моем примере ниже у меня есть T=5 временных шагов и S=3 символов.

positions представляет распределение портфеля для каждого символа на каждом временном шаге , Например, если у меня есть 5% актива 1, 10% актива 2 и 85% актива 3 на временном шаге 4, тогда positions[4] равно [0.05, 0.1, 0.85].

При покупке (актив от t до t+1 увеличивается), следует использовать цены ask. При продаже следует использовать цены bid. Это потому, что я предполагаю стратегию, при которой я покупаю / продаю только по рыночным ордерам, поэтому мне нужно каждый раз «пересекать спред».

Как я могу рассчитать свою прибыль, учитывая список позиций во времени, цены спроса и цены предложения?

Для простоты все цены указаны по первому активу (цена которого всегда равна 1), а начальная позиция равна [1, 0, 0].

Что бы я хотел это векторизованная реализация функции compute_returns_loop() (избавление от for -l oop за временные шаги).

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
T,S=5,3

asks = np.array([[1,1,1,1,1], [3, 3, 3.5, 4, 4], [13, 13, 15, 17, 21]]).T # (T, S)
bids = np.array([[1,1,1,1,1], [1, 1, 2.5, 2, 3], [11, 11, 13, 15, 19]]).T # (T, S)

positions_test_1 = np.array([[1, 0, 0], [1, 0, 0], [1,   0, 0  ], [1,   0, 0  ], [1, 0, 0]]) # (T, S)
positions_test_2 = np.array([[1, 0, 0], [1, 0, 0], [0,   0, 1  ], [0,   0, 1  ], [1, 0, 0]]) # (T, S)
positions_test_3 = np.array([[1, 0, 0], [1, 0, 0], [0.5, 0, 0.5], [0.5, 0, 0.5], [1, 0, 0]]) # (T, S)
positions_test_4 = np.array([[1, 0, 0], [1, 0, 0], [0,   0, 1  ], [1,   0, 0  ], [1, 0, 0]]) # (T, S)

# Quick visualization
plt.plot(asks[:, 2])
plt.plot(bids[:, 2])

# Here absolute means in the currency of the respective asset
# positions are expressed as ratio of the total portfolio allocation
def compute_returns_loop(positions, asks, bids):
    mids = (asks + bids) / 2

    current_absolute_position = positions[0].astype(np.float)
    for t in range(1, asks.shape[0]):
        unrealized_worth = (mids[t] * current_absolute_position).sum()
        target_absolute_position = positions[t] / mids[t] * unrealized_worth
        absolute_transactions = target_absolute_position - current_absolute_position
        current_absolute_position[1:] += absolute_transactions[1:]
        cost = np.where(absolute_transactions[1:] > 0, asks[t, 1:], bids[t, 1:])
        current_absolute_position[0] -= (cost * absolute_transactions[1:]).sum()
    return current_absolute_position[0]

def compute_returns_vectorized(positions, asks, bids):
    mids = (asks + bids) / 2
    # TODO
    return None

print(compute_returns_loop(positions_test_1, asks, bids)) # should be  1
print(compute_returns_loop(positions_test_2, asks, bids)) # should be ~1.2
print(compute_returns_loop(positions_test_3, asks, bids)) # should be ~1.1
print(compute_returns_loop(positions_test_4, asks, bids)) # should be  1

# replacing compute_returns_loop with compute_returns_vectorized should give approximately the same results
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...