psemdel/py-trading-bot

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 ?