Я пытаюсь создать векторизованную / параллельную программу тестирования на истории.Я реализовал последовательную версию с циклами, но теперь я застрял в векторизации функциональности.Я собираюсь использовать Pandas / Numpy для этого, вот краткий план:
Есть 2 заданных столбца, слева количество заказа (будет добавлено к позиции), право - остановок (если остановка 1, позиция сбрасывается в 0)
M = [[0.1, 0], # left column is order quantity, right is stop
[0.1, 0],
[0.5, 0],
[0.5, 0],
[0.3, 0],
[-0.3, 0], # negative order quantity means short or sell
[-0.1, 1]] # right column (stop) is 1, so position is reset to 0
И 2 столбца, которые я хочу вычислить на основе исходной матрицы M: левый столбец равен позиция (в диапазоне от -1 до 1, но не может выходить за пределы) на основе количество заказа и правый столбец количество выполненного заказа
R = [[0.1, 0.1],
[0.2, 0.1],
[0.7, 0.5], # position (left column) is equal to cumsum of order quantity (from last stop trigger)
[1, 0.3], # executed quantity is < order quantity as it's the remainder to position's max of 1
[1, 0],
[0.7, -0.3],
[-0.1, -0.8]] # stop triggered, so position is reset to 0, and then -0.1 in order quantity is executed
- Позиция в основном является суммой количества заказа, но только до 1 или -1, и только в том случае, если остановки не срабатывают
- Количество выполненного заказа - это либо количество заказа, если пределы позиции не превышены, либо остаток
- Останов (когда 1) сбрасывает положение на 0
Проблема в том, что каждое условие основано на другом.Означает ли это, что эта задача не может быть решена параллельно?
Я могу представить себе подход с количественным суммированием и индексами, где срабатывает останов, применяемый к суммируемому количеству для вычисления выполненного количества.Буду признателен за любые советы по элегантным способам решения этой проблемы.Может быть, какие функции Numpy нужно рассмотреть, кроме cumsum.
Редактировать: очень упрощенная версия последовательной версии:
orders = [{'quantity': 0.1,'stop': 0},{'quantity': 0.1,'stop': 0},{'quantity': 0.5,'stop': 0},{'quantity': 0.5,'stop': 0},{'quantity': 0.3,'stop': 0},{'quantity': -0.3,'stop': 0},{'quantity': -0.1,'stop': 1}]
position = 0
for order in orders:
position_beginning = position
if order['stop'] == 1:
position = 0
if order['quantity']+position <= 1 and order['quantity']+position >= -1:
position += order['quantity']
elif position < 0 and order['quantity'] < 0:
position = -1
elif position > 0 and order['quantity'] > 0:
position = 1
executed_quantity = abs(position - position_beginning) * (1 if position > position_beginning else -1)
print(position, executed_quantity)
В реальном приложении объемы заказов намного сложнее,например, разделен на под количества.Тот факт, что backtester должен выполнять миллионы заказов с суб-количествами, делает этот процесс очень медленным, используя этот циклический подход.