Skip to content

Instantly share code, notes, and snippets.

@Klaudioz
Created October 11, 2024 15:07
Show Gist options
  • Select an option

  • Save Klaudioz/2e35fa7d288bc34028189a46bb92c890 to your computer and use it in GitHub Desktop.

Select an option

Save Klaudioz/2e35fa7d288bc34028189a46bb92c890 to your computer and use it in GitHub Desktop.
import pandas as pd
import numpy as np
from sqlalchemy import create_engine
from gym import spaces
from stable_baselines3 import PPO
from finrl.apps import apps
from finrl.meta.env_stock_trading.env_stocktrading import StockTradingEnv
from finrl.meta.preprocessor.preprocessors import FeatureEngineer
# Connect to PostgreSQL database
engine = create_engine('postgresql://username:password@localhost:5432/your_database')
# Fetch OHLCV (Open, High, Low, Close, Volume) data for MEME pair
query = """
SELECT datetime, open, high, low, close, volume
FROM ohlcv_table
WHERE symbol = 'MEME' -- Replace with your desired symbol
ORDER BY datetime
"""
df = pd.read_sql(query, engine)
# Calculate Volume Weighted Average Price (VWAP)
# VWAP is a trading benchmark that gives the average price a security has traded at throughout the day, based on both volume and price
df['vwap'] = (df['close'] * df['volume']).cumsum() / df['volume'].cumsum()
# Perform feature engineering on the dataset
fe = FeatureEngineer(
use_technical_indicator=True,
tech_indicator_list=['vwap', 'volume']
)
processed = fe.preprocess_data(df)
# Define a custom environment for VWAP-based trading with a trailing stop
class VWAPTrailingStopEnv(StockTradingEnv):
def __init__(self, df, initial_amount=100000, trading_cost_pct=0.001, trailing_stop_pct=0.02):
super().__init__(df, initial_amount=initial_amount, trading_cost_pct=trading_cost_pct)
self.trailing_stop_pct = trailing_stop_pct # Percentage for trailing stop loss
self.highest_price = 0 # Tracks the highest price seen for trailing stop
def step(self, action):
# Check if we've reached the end of the dataset
self._done = self.day >= len(self.df.index.unique()) - 1
if self._done:
return self._get_observation(), self.reward, self._done, {}
self.current_price = self.df.loc[self.day, "close"].values[0]
# VWAP entry logic: Buy if price is above VWAP and we're not in a position
vwap = self.df.loc[self.day, "vwap"].values[0]
if self.current_price > vwap and self.state[0] == 0:
action = 1 # Buy
# Trailing stop loss logic: Sell if price drops below the trailing stop level
if self.state[0] > 0: # If we're in a long position
self.highest_price = max(self.highest_price, self.current_price)
if self.current_price <= self.highest_price * (1 - self.trailing_stop_pct):
action = 2 # Sell
# Execute the action and move to the next day
self._take_action(action)
self.day += 1
self.reward = self._get_reward()
return self._get_observation(), self.reward, self._done, {}
# Set up the trading environment
env = VWAPTrailingStopEnv(processed)
# Train the agent using Proximal Policy Optimization (PPO) algorithm
model = PPO("MlpPolicy", env, verbose=1)
model.learn(total_timesteps=10000)
# Backtest the trained model
df_account_value, df_actions = apps.test_one_episode(model, env)
# Calculate returns and Sharpe ratio
returns = (df_account_value['account_value'].pct_change().dropna())
sharpe_ratio = np.sqrt(252) * returns.mean() / returns.std() # Annualized Sharpe ratio
# Print the results
print(f"Final account value: ${df_account_value['account_value'].iloc[-1]:.2f}")
print(f"Sharpe ratio: {sharpe_ratio:.2f}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment