Minimum Profit Strategy
Introduction
This trading strategy takes new spread values one by one and allows checking if the conditions to open a position are fulfilled with each new timestamp and value provided. This allows for easier integration of these strategies into an existing data pipeline. Also, the strategy object keeps track of open and closed trades and the supporting information related to them.
Minimum Profit Strategy
The Minimum Profit class from the Cointegration Approach generates
optimal entry and exit levels (buy_level
, close_level
, sell_level
) as well as number of
shares (shares_A
, shares_B
) to trade per asset in a cointegrated pair. The strategy described in this
section of the documentation can be used to trade those generated signals.
The signal generation process relies on the performance of the spread, which is calculated as:
Where the \(beta\) parameter is given by the Minimum Profit class. If the spread value drops below
the buy_level
, a buy trade should be opened, meaning we should go shares_A
long and shares_B
short.
If the spread value rises above the sell_level
, a sell trade should be opened, so we short shares_B
and
go long shares_A
. Upon reaching the close_level
, a buy or a sell trade should be closed. This strategy
assumes only one open trade at a time.
The strategy object is initialized with a number of shares and optimal levels.
The update_spread_value
method allows adding new spread values one by one - when they are available.
At each stage, the check_entry_signal
method checks if the trade should be entered according to the
above-described logic. If the trade should be opened, it can be added to the internal dictionary using the
add_trade
method.
As well, the update_trades
method can be used to check if any trades should be closed.
If so, the internal dictionaries are updated, and the list of the closed trades at this stage is returned.
Implementation
- class MinimumProfitTradingRule(shares: array, optimal_levels: array, spread_window: int = 10)
This class implements trading strategy from the Minimum Profit Optimization method from the paper by Lin, Y.-X., McCrae, M., and Gulati, C. “Loss protection in pairs trading through minimum profit bounds: a cointegration approach”
The strategy generates a signal by when
spread <= buy_level
orspread => sell_level
and exit from a position when|spread| <= |close_level|
.This strategy allows only one open trade at a time.
- __init__(shares: array, optimal_levels: array, spread_window: int = 10)
Class constructor.
- Parameters:
shares – (np.array) Number of shared to trade per leg in the cointegration pair.
optimal_levels – (np.array) Optimal levels to enter aenter and close a trade.
spread_window – (int) Number of previous spread values to print when reporting trades.
- add_trade(start_timestamp: Timestamp, side_prediction: int, uuid: UUID | None = None, shares: array | None = None)
Adds a new trade to track. Calculates trigger prices and trigger timestamp.
- Parameters:
start_timestamp – (pd.Timestamp) Timestamp of the future label.
side_prediction – (int) External prediction for the future label.
uuid – (str) Unique identifier used to link label to tradelog action.
shares – (np.array) Number of shares bought and sold per asset.
- check_entry_signal() tuple
Function which checks entry condition for a spread series based on self.entry_buy_signal, self.entry_sell_signal, self.spread_series.
- Returns:
(tuple) Tuple of boolean entry flag and side (if entry flag is True).
- update_spread_value(latest_spread_value: float)
Adds latest spread value to self.spread_series. Once it is done - one can check entry/exit signals.
- Parameters:
latest_spread_value – (float) Latest spread value.
- update_trades(update_timestamp: Timestamp) list
Checks whether any of the thresholds are triggered and currently open trades should be closed.
- Parameters:
update_timestamp – (pd.Timestamp) New timestamp to check vertical threshold.
- Returns:
(list) List of closed trades.
Example
# Importing packages
import pandas as pd
import numpy as np
# Importing ArbitrageLab tools
from arbitragelab.cointegration_approach.minimum_profit import MinimumProfit
from arbitragelab.trading import MinimumProfitTradingRule
# Using MinimumProfit as optimizer ...
# Generate optimal trading levels and number of shares to trade
num_of_shares, optimal_levels = optimizer.get_optimal_levels(optimal_ub,
minimum_profit,
beta_eg,
epsilon_t_eg)
# Calculating spread
spread = optimizer.construct_spread(data, beta_eg)
# Creating a strategy
strategy = MinimumProfitTradingRule(num_of_shares, optimal_levels)
# Adding initial spread value
strategy.update_spread_value(spread[0])
# Feeding spread values to the strategy one by one
for time, value in spread.iteritems():
strategy.update_spread_value(value)
# Checking if logic for opening a trade is triggered
trade, side = strategy.check_entry_signal()
# Adding a trade if we decide to trade signal
if trade:
strategy.add_trade(start_timestamp=time, side_prediction=side)
# Update trades, close if logic is triggered
close = strategy.update_trades(update_timestamp=time)
# Checking currently open trades
open_trades = strategy.open_trades
# Checking all closed trades
closed_trades = strategy.closed_trades
Research Notebooks
The following research notebook can be used to better understand the Strategy described above.