-
Notifications
You must be signed in to change notification settings - Fork 138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Draft] Minimum Profit Condition Optimization - Cointegration Approach #7
Conversation
# Description Implementations in this module are based on the book by Ernest P. Chan **"Algorithmic Trading: Winning Strategies and Their Rationale"**. Implemented features are: - Johansen cointegration test - Engle-Granger cointegration test - Half-life of mean reversion function - Linear trading strategy - Bollinger Bands trading strategy ## Type of change - [x] New feature (non-breaking change which adds functionality) - [x] This change requires a documentation update # How Has This Been Tested? This unit tests file was created to test the added functions: - [x] test_mean_reversion.py **Test Configuration**: * Windows 10 * PyCharm # Checklist: - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [x] Any dependent changes have been merged and published in downstream modules
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Went over the code part. It's great that we're close to getting all the functionality ready 👍
Left some comments covering possible style improvements and code restructuring. We'll discuss some parts in more detail over a call.
minimum_profit/MinimumProfit.py
Outdated
@@ -0,0 +1,420 @@ | |||
import warnings |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add a copyright note to every code and unit test file.
minimum_profit/MinimumProfit.py
Outdated
@@ -0,0 +1,420 @@ | |||
import warnings | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, these files should be inside the arbitragelab
folder.
We will solve the questions regarding naming during the call.
minimum_profit/MinimumProfit.py
Outdated
import numpy as np | ||
import pandas as pd | ||
import statsmodels.api as sm | ||
from mlfinlab.statistical_arbitrage import JohansenPortfolio, EngleGrangerPortfolio |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A reminder to later redirect this to functions from the ArbitrageLab.
minimum_profit/MinimumProfit.py
Outdated
Build a pd.DataFrame of both series for cointegration error calculation. | ||
Initialize a built-in trade book with position, entry price, P&L, and number of trades information. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can try to simplify this by requiring a pd.DataFrame as an input format.
minimum_profit/MinimumProfit.py
Outdated
:param price_s1: (pd.Series or np.array) Share S1 price series | ||
:param price_s2: (pd.Series or np.array) Share S2 price series | ||
:param s1_name: (str) Share S1 name | ||
:param s2_name: (str) Share S2 name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the right style for variable descriptions, but please add fulls stops at the end.
minimum_profit/MinimumProfit.py
Outdated
if capital_req <= dollar_constraint: | ||
# Record the entry price. | ||
self._entry_price = current_price | ||
|
||
# Do we open a U-trade or L-trade? | ||
if trade_df_with_cond['otc_U'].iloc[i]: | ||
|
||
# U-trade, short share S1, long share S2 | ||
self._position = position * np.array([-1, 1]) | ||
current_trade = 1 | ||
|
||
elif allow_ltrade and trade_df_with_cond['otc_L'].iloc[i]: | ||
|
||
# L-trade, long share S1, short share S2 | ||
self._position = position * np.array([1, -1]) | ||
current_trade = -1 | ||
else: | ||
# No opening condition met, forward to next day | ||
continue |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll have to refactor this to make it more compact and readable. I'll help.
minimum_profit/MinimumProfit.py
Outdated
Methods: | ||
train_test_split(date_cutoff, num_cutoff): A method that splits the price data into a training set and | ||
a test set according to the cutoff. In-sample simulation can be done when both cutoffs are set to None. | ||
fit(train_df): Derive the cointegration coefficient, cointegration error, AR(1) cofficient and the fitted | ||
residual of the AR(1) process. | ||
optimize(ar_coeff, epsilon_t, ar_resid, horizon, granularity): | ||
Optimize the upper bound for U-trade by optimizing minimum trade profit | ||
trade(self, trade_df, upper_bound, minimum_profit, beta, epsilon_t, **kwarg): | ||
Simulate trades applying the optimal upper bound and lower bound for U-trade and L-trade, respectively. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if we'll keep this style for internal methods. But it's ok if you write them for now as:
Methods:
- train_...
....
- fit ...
....
"ar_coeff": 0.1, | ||
"white_noise_var": 0.5, | ||
"constant_trend": 13. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should later make these input parameters instead of hardcoded ones.
Setter for price simulation parameters | ||
:param param: (str) Parameter dictionary key | ||
:param value: (float) Parameter value | ||
:return: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Returns can be removed if it's a setter method.
:return: | ||
(np.array, np.array, np.array) Price series of share S1, price series of share S2, and cointegration error. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't move the variable description to the next line like this. It should be:
:return: (np.array, np.array, np.array) Price series of share S1, price series of share S2,
and cointegration error.
This PR was moved to PR#19. |
Description
Implementations in this module are based on the following paper:
Lin, Y.-X., McCrae, M., and Gulati, C. (2006). Loss protection in pairs trading through minimum profit bounds: A cointegration approach.Journal of Applied Mathematics and Decision Sciences, 2006(1):1–14.
Puspaningrum, H., Lin, Y.-X., and Gulati, C. M. (2010). Finding the optimal pre-set boundaries for pairs trading strategy based on cointegration technique. Journal of Statistical Theory and Practice, 4(3):391–419.
Implemented features are:
Dependency:
Type of change
How Has This Been Tested?
This unit tests file was created to test the added functions:
Test Configuration:
Checklist: