Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- !pip install alpaca-trade-api
- import alpaca_trade_api as alpaca
- from alpaca_trade_api.rest import REST, TimeFrame, TimeFrameUnit
- # alpaca
- YOUR_API_KEY_ID = '*****************'
- YOUR_API_SECRET_KEY = '**********************'
- api = alpaca.REST(YOUR_API_KEY_ID, YOUR_API_SECRET_KEY, 'https://paper-api.alpaca.markets')
- ####################
- start_date = '2023-01-01'
- end_date = '2024-12-31'
- def get_data(ticker):
- data = api.get_bars(ticker, TimeFrame(1, TimeFrameUnit.Minute), start_date, end_date, adjustment='all').df # need to use adjustment='all' to get properly adjusted close price
- data = data.tz_convert('America/Los_angeles')
- data = data.between_time('6:30', '13:00') # when market is open
- return data
- tqqq, sqqq = get_data('TQQQ'), get_data('SQQQ')
- #########################
- import plotly.graph_objects as go
- import pandas as pd
- import numpy as np
- import matplotlib.pyplot as plt
- class StraddleSimulator:
- def __init__(self, tqqq, sqqq, initial_equity=1000, stop_loss_pct=0.02):
- self.tqqq = tqqq
- self.sqqq = sqqq
- self.initial_equity = initial_equity
- self.stop_loss_pct = stop_loss_pct
- self.equity = initial_equity
- self.results = []
- def preprocess_data(self):
- self.tqqq['symbol'] = 'TQQQ'
- self.sqqq['symbol'] = 'SQQQ'
- self.data = pd.concat([self.tqqq, self.sqqq])
- self.data['date'] = self.data.index.date
- def simulate_day(self, date, symbol):
- daily_data = self.data[(self.data['date'] == date) & (self.data['symbol'] == symbol)]
- if daily_data.empty:
- return
- open_price = daily_data.iloc[0]['open']
- shares = self.equity / 2 / open_price
- high_price = open_price
- for _, row in daily_data.iterrows():
- high_price = max(high_price, row['high'])
- stop_price = high_price * (1 - self.stop_loss_pct)
- if row['low'] <= stop_price and stop_price < row['open']: # only exit if the stop price is less than the open. otherwise you may erroneously exit in a large bull candle
- exit_price = stop_price
- break
- else:
- exit_price = daily_data.iloc[-1]['close']
- pnl = (exit_price - open_price) * shares
- self.equity += pnl
- self.results.append({
- 'date': date,
- 'symbol': symbol,
- 'open_price': open_price,
- 'exit_price': exit_price,
- 'shares': shares,
- 'pnl': pnl,
- 'equity': self.equity,
- 'entry_time': daily_data.iloc[0].name,
- 'exit_time': row.name if 'exit_price' in locals() else daily_data.iloc[-1].name,
- })
- def run_simulation(self):
- self.preprocess_data()
- for date in self.data['date'].unique():
- for symbol in ['TQQQ', 'SQQQ']:
- self.simulate_day(date, symbol)
- self.results_df = pd.DataFrame(self.results)
- def calculate_metrics(self):
- """Calculate performance metrics."""
- unique_dates = len(self.results_df['date'].unique())
- self.cagr = ((self.equity / self.initial_equity) ** (1 / (unique_dates / 252))) - 1
- # self.win_rate = (self.results_df['pnl'] > 0).mean()
- self.win_rate = self.calculate_win_rate()
- self.sharpe_ratio = self.results_df['pnl'].mean() / self.results_df['pnl'].std() * np.sqrt(252)
- self.max_drawdown = (self.results_df['equity'] / self.results_df['equity'].cummax() - 1).min()
- def calculate_win_rate(self):
- """Calculate win rate based on which symbol performs better on each day."""
- wins = 0
- losses = 0
- tqqq_wins = 0
- sqqq_wins = 0
- ties = 0
- total_days = 0
- for date in self.results_df['date'].unique():
- daily_results = self.results_df[self.results_df['date'] == date]
- if len(daily_results) == 2: # Ensure both TQQQ and SQQQ have results
- # Calculate profits for TQQQ and SQQQ
- tqqq_result = daily_results[daily_results['symbol'] == 'TQQQ']
- sqqq_result = daily_results[daily_results['symbol'] == 'SQQQ']
- tqqq_profit = (tqqq_result['exit_price'].values[0] - tqqq_result['open_price'].values[0]) * tqqq_result['shares'].values[0]
- sqqq_profit = (sqqq_result['exit_price'].values[0] - sqqq_result['open_price'].values[0]) * sqqq_result['shares'].values[0]
- # Compare profits
- if tqqq_profit + sqqq_profit > 0:
- wins += 1
- elif tqqq_profit + sqqq_profit < 0:
- losses += 1
- total_days += 1
- win_rate = wins/(wins+losses)
- print(f"Wins: {wins}, losses: {losses}")
- print(f"Win Rate: {win_rate:.2%}")
- return win_rate
- def print_metrics(self):
- """Print calculated metrics."""
- print(f"CAGR: {self.cagr:.2%}")
- print(f"Win Rate: {self.win_rate:.2%}")
- print(f"Sharpe Ratio: {self.sharpe_ratio:.2f}")
- print(f"Max Drawdown: {self.max_drawdown:.2%}")
- def plot_equity_curve_matplotlib(self):
- """Plot the equity curve."""
- plt.figure(figsize=(12, 6))
- plt.plot(self.results_df['date'], self.results_df['equity'], label='Equity Curve')
- plt.title('Equity Curve')
- plt.xlabel('Date')
- plt.ylabel('Equity')
- plt.legend()
- plt.grid()
- plt.show()
- def plot_equity_curve(self,h,w):
- # Create the Plotly figure
- fig = go.Figure()
- # Add the equity curve
- fig.add_trace(go.Scatter(
- x=self.results_df['date'],
- y=self.results_df['equity'],
- mode='lines',
- name='Equity Curve',
- line=dict(color='blue')
- ))
- # Update layout for better appearance
- fig.update_layout(
- title="Equity Curve",
- xaxis_title="Date",
- yaxis_title="Equity Value",
- template="plotly_white",
- xaxis=dict(showgrid=True),
- yaxis=dict(showgrid=True),
- height=h,
- width=w
- )
- # Show the plot
- fig.show()
- def plot_day_candles(self, date):
- """Plot separate candlestick charts for TQQQ and SQQQ with entry and exit markers."""
- day_data = self.data[self.data['date'] == pd.to_datetime(date).date()]
- if day_data.empty:
- print(f"No data available for {date}.")
- return
- for symbol in ['TQQQ', 'SQQQ']:
- symbol_data = day_data[day_data['symbol'] == symbol]
- if symbol_data.empty:
- continue
- fig = go.Figure()
- # Plot candlestick chart
- fig.add_trace(go.Candlestick(
- x=symbol_data.index,
- open=symbol_data['open'],
- high=symbol_data['high'],
- low=symbol_data['low'],
- close=symbol_data['close'],
- name=f'{symbol} Candlestick',
- ))
- # Add markers for entry and exit
- result = self.results_df[(self.results_df['date'] == pd.to_datetime(date).date()) &
- (self.results_df['symbol'] == symbol)]
- if not result.empty:
- entry_time = result.iloc[0]['entry_time']
- exit_time = result.iloc[0]['exit_time']
- entry_price = result.iloc[0]['open_price']
- exit_price = result.iloc[0]['exit_price']
- fig.add_trace(go.Scatter(
- x=[entry_time],
- y=[entry_price],
- mode='markers+text',
- marker=dict(color='green', size=10),
- name='Entry',
- text='Entry',
- textposition='top center'
- ))
- fig.add_trace(go.Scatter(
- x=[exit_time],
- y=[exit_price],
- mode='markers+text',
- marker=dict(color='red', size=10),
- name='Exit',
- text='Exit',
- textposition='top center'
- ))
- # Layout updates
- fig.update_layout(
- title=f"{symbol} Candlestick Chart for {date}",
- xaxis_title="Time",
- yaxis_title="Price",
- legend_title="Legend",
- xaxis_rangeslider=dict(visible=False), # Remove the slider
- )
- # Show plot
- fig.show()
- ######################
- # After running the simulation
- simulator = StraddleSimulator(tqqq, sqqq, initial_equity=1000, stop_loss_pct=0.02)
- simulator.run_simulation()
- simulator.calculate_metrics()
- simulator.print_metrics()
- simulator.plot_equity_curve(500,500)
- ###########################
- # Plot candles for a specific day
- start_date = "2024-07-01"
- end_date = "2024-07-31"
- # Generate the list of dates
- # date_list = pd.date_range(start=start_date, end=end_date).strftime('%Y-%m-%d').tolist()
- date_list = pd.date_range(start=start_date, end=end_date).strftime('%Y-%m-%d').tolist()
- simulator.results_df['date_string'] = [d.strftime('%Y-%m-%d') for d in simulator.results_df['date']]
- for date in date_list:
- simulator.plot_day_candles(date)
- a3 = simulator.results_df[(simulator.results_df.date_string == date)]['pnl'].sum()/1000 * 100
- print(f'{date}: ',f'{a3:.2f}%')
- ##############################
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement