Add strat
Closed this issue · 2 comments
I have a simple strat boilerplate im using for quant im wondering if you can port it over to your framework so I can use my strats on your bot. I am having a hard time grasping everything going on with your setup. import pandas as pd
import yfinance as yf
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import morlet
Download historical data for S&P 500 from Yahoo Finance
df = yf.download('^GSPC', start='2010-01-01', end='2023-06-23')
Use adjusted close prices
df['close'] = df['Adj Close']
Apply discrete Morlet wavelet transform
def wavelet_transform(signal, window_size):
wavelet = morlet(window_size, 5)
transformed_signal = np.convolve(signal, wavelet, mode='same')
return transformed_signal
df['wavelet'] = wavelet_transform(df['close'], window_size=51)
Calculate differences to identify up and down movements
df['price_diff'] = df['close'].diff()
Separate into monotonic states
df['up'] = df['price_diff'].clip(lower=0)
df['down'] = df['price_diff'].clip(upper=0) * -1
Initialize columns for normalized up and down movements
df['up_norm'] = 0.0
df['down_norm'] = 0.0
Compute ranks using the entire price data
df['up_norm'] = df['up'].rank(pct=True)
df['down_norm'] = df['down'].rank(pct=True)
Calculate log returns
df['log_returns'] = np.log(df['close']).diff()
Define position sizing model
positionSizingModel = 'percentage' # Choose the position sizing model ('percentage', 'fixed_ratio', 'secure_f', 'margin_based')
Position sizing parameters
accountEquity = 100000 # Account equity
riskPercentage = 1.5 # Risk percentage per trade
stopLossPips = 250 # Stop loss in pips
percentageVolatility = 2.5 # Percentage volatility model
fixedRatio = 0.02 # Fixed ratio model
secureF = 0.01 # Secure (f) model
marginBasedSize = 0.01 # Margin-based size model
Calculate position size
contractSize = 5000
accountSize = accountEquity * riskPercentage / 100.0
if positionSizingModel == 'percentage':
positionSize = accountSize * percentageVolatility / (stopLossPips * contractSize)
elif positionSizingModel == 'fixed_ratio':
positionSize = accountEquity * fixedRatio / (stopLossPips * contractSize)
elif positionSizingModel == 'secure_f':
positionSize = accountEquity * secureF / (stopLossPips * contractSize)
elif positionSizingModel == 'margin_based':
margin = accountEquity * marginBasedSize
positionSize = margin / stopLossPips
print("Position Size:", positionSize)
Define trading logic
df['position_size'] = np.where(df['up_norm'] > 0.95, positionSize, np.where(df['down_norm'] > 0.95, -positionSize, np.nan))
df['position_size'] = df['position_size'].fillna(method='ffill')
Compute returns
df['returns'] = df['log_returns'] * df['position_size']
Calculate equity curve
df['equity_curve'] = (df['returns'] + 1).cumprod() * accountEquity
Plot equity curve with 'Close' price
fig, ax1 = plt.subplots(figsize=(10, 5))
ax1.plot(df.index, df['equity_curve'], color='blue', label='Equity Curve')
ax1.set_xlabel('Date')
ax1.set_ylabel('Equity', color='blue')
ax1.set_title('Equity Curve and Close Price')
ax1.tick_params('y', colors='blue')
ax2 = ax1.twinx()
ax2.plot(df.index, df['close'], color='red', label='Close Price')
ax2.set_ylabel('Close Price', color='red')
ax2.tick_params('y', colors='red')
fig.tight_layout()
Add legend
lines_1, labels_1 = ax1.get_legend_handles_labels()
lines_2, labels_2 = ax2.get_legend_handles_labels()
lines = lines_1 + lines_2
labels = labels_1 + labels_2
plt.legend(lines, labels)
plt.show()
Hi, thx for the suggestion. I can definitely understand that it is still a bit difficult to understand everything. I am working on it, but there is still a long way.
Basically, for 80% of what you write should go in core/indicator, where the vector calculations are performed. You can have a look at VBTSUPERTREND, it was coded directly by vbt author. The indicator uses normally only numpy functions to be faster. So it performs on each symbol separately. But of course, you could do a fit of post processing with pandas, if you want.
To download historical data, go in core/data_manager.
all_symbols=constants.NYSE
index="^GSPC"
It will save two files in core: actions (so here the NYSE prices) and index (^GSPC).
I see here, the first small issue. Vbt does not seem to implement the column "Adj Close". Let's use "Close" instead.
My bot is also design to perform automatic orders depending on clear signal. Not to plot curve, that you need to read manually.
I will try to implement your strategy. I cannot promess, in which month to be honest. I am in the middle of a total reworking of the core of the code, it will take me a while.
I wrote it, but I cannot see how to decide which order. Also the wavelet is not used? Actually the return calculation and so on is taken care by vbt. You just need to define the entries and exits. I suppose it related to equity_curve != NaN ?