Advertisement
BAMpas

Untitled

Jan 1st, 2025 (edited)
35
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.55 KB | None | 0 0
  1. !pip install alpaca-trade-api
  2. import alpaca_trade_api as alpaca
  3. from alpaca_trade_api.rest import REST, TimeFrame, TimeFrameUnit
  4.  
  5. # alpaca
  6. YOUR_API_KEY_ID = '*****************'
  7. YOUR_API_SECRET_KEY = '**********************'
  8. api = alpaca.REST(YOUR_API_KEY_ID, YOUR_API_SECRET_KEY, 'https://paper-api.alpaca.markets')
  9.  
  10. ####################
  11.  
  12. start_date = '2023-01-01'
  13. end_date = '2024-12-31'
  14.  
  15. def get_data(ticker):
  16. 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
  17. data = data.tz_convert('America/Los_angeles')
  18. data = data.between_time('6:30', '13:00') # when market is open
  19. return data
  20.  
  21. tqqq, sqqq = get_data('TQQQ'), get_data('SQQQ')
  22.  
  23. #########################
  24.  
  25.  
  26. import plotly.graph_objects as go
  27. import pandas as pd
  28. import numpy as np
  29. import matplotlib.pyplot as plt
  30.  
  31. class StraddleSimulator:
  32. def __init__(self, tqqq, sqqq, initial_equity=1000, stop_loss_pct=0.02):
  33. self.tqqq = tqqq
  34. self.sqqq = sqqq
  35. self.initial_equity = initial_equity
  36. self.stop_loss_pct = stop_loss_pct
  37. self.equity = initial_equity
  38. self.results = []
  39.  
  40. def preprocess_data(self):
  41. self.tqqq['symbol'] = 'TQQQ'
  42. self.sqqq['symbol'] = 'SQQQ'
  43. self.data = pd.concat([self.tqqq, self.sqqq])
  44. self.data['date'] = self.data.index.date
  45.  
  46. def simulate_day(self, date, symbol):
  47. daily_data = self.data[(self.data['date'] == date) & (self.data['symbol'] == symbol)]
  48. if daily_data.empty:
  49. return
  50.  
  51. open_price = daily_data.iloc[0]['open']
  52. shares = self.equity / 2 / open_price
  53.  
  54. high_price = open_price
  55. for _, row in daily_data.iterrows():
  56. high_price = max(high_price, row['high'])
  57. stop_price = high_price * (1 - self.stop_loss_pct)
  58. 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
  59. exit_price = stop_price
  60. break
  61. else:
  62. exit_price = daily_data.iloc[-1]['close']
  63.  
  64. pnl = (exit_price - open_price) * shares
  65. self.equity += pnl
  66.  
  67. self.results.append({
  68. 'date': date,
  69. 'symbol': symbol,
  70. 'open_price': open_price,
  71. 'exit_price': exit_price,
  72. 'shares': shares,
  73. 'pnl': pnl,
  74. 'equity': self.equity,
  75. 'entry_time': daily_data.iloc[0].name,
  76. 'exit_time': row.name if 'exit_price' in locals() else daily_data.iloc[-1].name,
  77. })
  78.  
  79. def run_simulation(self):
  80. self.preprocess_data()
  81. for date in self.data['date'].unique():
  82. for symbol in ['TQQQ', 'SQQQ']:
  83. self.simulate_day(date, symbol)
  84. self.results_df = pd.DataFrame(self.results)
  85.  
  86. def calculate_metrics(self):
  87. """Calculate performance metrics."""
  88. unique_dates = len(self.results_df['date'].unique())
  89. self.cagr = ((self.equity / self.initial_equity) ** (1 / (unique_dates / 252))) - 1
  90. # self.win_rate = (self.results_df['pnl'] > 0).mean()
  91. self.win_rate = self.calculate_win_rate()
  92. self.sharpe_ratio = self.results_df['pnl'].mean() / self.results_df['pnl'].std() * np.sqrt(252)
  93. self.max_drawdown = (self.results_df['equity'] / self.results_df['equity'].cummax() - 1).min()
  94.  
  95. def calculate_win_rate(self):
  96. """Calculate win rate based on which symbol performs better on each day."""
  97. wins = 0
  98. losses = 0
  99. tqqq_wins = 0
  100. sqqq_wins = 0
  101. ties = 0
  102. total_days = 0
  103.  
  104. for date in self.results_df['date'].unique():
  105. daily_results = self.results_df[self.results_df['date'] == date]
  106. if len(daily_results) == 2: # Ensure both TQQQ and SQQQ have results
  107. # Calculate profits for TQQQ and SQQQ
  108. tqqq_result = daily_results[daily_results['symbol'] == 'TQQQ']
  109. sqqq_result = daily_results[daily_results['symbol'] == 'SQQQ']
  110.  
  111. tqqq_profit = (tqqq_result['exit_price'].values[0] - tqqq_result['open_price'].values[0]) * tqqq_result['shares'].values[0]
  112. sqqq_profit = (sqqq_result['exit_price'].values[0] - sqqq_result['open_price'].values[0]) * sqqq_result['shares'].values[0]
  113.  
  114. # Compare profits
  115. if tqqq_profit + sqqq_profit > 0:
  116. wins += 1
  117. elif tqqq_profit + sqqq_profit < 0:
  118. losses += 1
  119.  
  120. total_days += 1
  121.  
  122. win_rate = wins/(wins+losses)
  123. print(f"Wins: {wins}, losses: {losses}")
  124. print(f"Win Rate: {win_rate:.2%}")
  125. return win_rate
  126.  
  127.  
  128. def print_metrics(self):
  129. """Print calculated metrics."""
  130. print(f"CAGR: {self.cagr:.2%}")
  131. print(f"Win Rate: {self.win_rate:.2%}")
  132. print(f"Sharpe Ratio: {self.sharpe_ratio:.2f}")
  133. print(f"Max Drawdown: {self.max_drawdown:.2%}")
  134.  
  135. def plot_equity_curve_matplotlib(self):
  136. """Plot the equity curve."""
  137. plt.figure(figsize=(12, 6))
  138. plt.plot(self.results_df['date'], self.results_df['equity'], label='Equity Curve')
  139. plt.title('Equity Curve')
  140. plt.xlabel('Date')
  141. plt.ylabel('Equity')
  142. plt.legend()
  143. plt.grid()
  144. plt.show()
  145.  
  146. def plot_equity_curve(self,h,w):
  147.  
  148. # Create the Plotly figure
  149. fig = go.Figure()
  150.  
  151. # Add the equity curve
  152. fig.add_trace(go.Scatter(
  153. x=self.results_df['date'],
  154. y=self.results_df['equity'],
  155. mode='lines',
  156. name='Equity Curve',
  157. line=dict(color='blue')
  158. ))
  159.  
  160. # Update layout for better appearance
  161. fig.update_layout(
  162. title="Equity Curve",
  163. xaxis_title="Date",
  164. yaxis_title="Equity Value",
  165. template="plotly_white",
  166. xaxis=dict(showgrid=True),
  167. yaxis=dict(showgrid=True),
  168. height=h,
  169. width=w
  170. )
  171.  
  172. # Show the plot
  173. fig.show()
  174.  
  175.  
  176. def plot_day_candles(self, date):
  177. """Plot separate candlestick charts for TQQQ and SQQQ with entry and exit markers."""
  178. day_data = self.data[self.data['date'] == pd.to_datetime(date).date()]
  179. if day_data.empty:
  180. print(f"No data available for {date}.")
  181. return
  182.  
  183. for symbol in ['TQQQ', 'SQQQ']:
  184. symbol_data = day_data[day_data['symbol'] == symbol]
  185. if symbol_data.empty:
  186. continue
  187.  
  188. fig = go.Figure()
  189.  
  190. # Plot candlestick chart
  191. fig.add_trace(go.Candlestick(
  192. x=symbol_data.index,
  193. open=symbol_data['open'],
  194. high=symbol_data['high'],
  195. low=symbol_data['low'],
  196. close=symbol_data['close'],
  197. name=f'{symbol} Candlestick',
  198. ))
  199.  
  200. # Add markers for entry and exit
  201. result = self.results_df[(self.results_df['date'] == pd.to_datetime(date).date()) &
  202. (self.results_df['symbol'] == symbol)]
  203. if not result.empty:
  204. entry_time = result.iloc[0]['entry_time']
  205. exit_time = result.iloc[0]['exit_time']
  206. entry_price = result.iloc[0]['open_price']
  207. exit_price = result.iloc[0]['exit_price']
  208.  
  209. fig.add_trace(go.Scatter(
  210. x=[entry_time],
  211. y=[entry_price],
  212. mode='markers+text',
  213. marker=dict(color='green', size=10),
  214. name='Entry',
  215. text='Entry',
  216. textposition='top center'
  217. ))
  218.  
  219. fig.add_trace(go.Scatter(
  220. x=[exit_time],
  221. y=[exit_price],
  222. mode='markers+text',
  223. marker=dict(color='red', size=10),
  224. name='Exit',
  225. text='Exit',
  226. textposition='top center'
  227. ))
  228.  
  229. # Layout updates
  230. fig.update_layout(
  231. title=f"{symbol} Candlestick Chart for {date}",
  232. xaxis_title="Time",
  233. yaxis_title="Price",
  234. legend_title="Legend",
  235. xaxis_rangeslider=dict(visible=False), # Remove the slider
  236. )
  237.  
  238. # Show plot
  239. fig.show()
  240.  
  241.  
  242.  
  243. ######################
  244.  
  245.  
  246. # After running the simulation
  247. simulator = StraddleSimulator(tqqq, sqqq, initial_equity=1000, stop_loss_pct=0.02)
  248. simulator.run_simulation()
  249. simulator.calculate_metrics()
  250. simulator.print_metrics()
  251. simulator.plot_equity_curve(500,500)
  252.  
  253.  
  254. ###########################
  255.  
  256.  
  257. # Plot candles for a specific day
  258.  
  259. start_date = "2024-07-01"
  260. end_date = "2024-07-31"
  261.  
  262. # Generate the list of dates
  263. # date_list = pd.date_range(start=start_date, end=end_date).strftime('%Y-%m-%d').tolist()
  264. date_list = pd.date_range(start=start_date, end=end_date).strftime('%Y-%m-%d').tolist()
  265. simulator.results_df['date_string'] = [d.strftime('%Y-%m-%d') for d in simulator.results_df['date']]
  266.  
  267. for date in date_list:
  268. simulator.plot_day_candles(date)
  269. a3 = simulator.results_df[(simulator.results_df.date_string == date)]['pnl'].sum()/1000 * 100
  270. print(f'{date}: ',f'{a3:.2f}%')
  271.  
  272.  
  273. ##############################
  274.  
  275.  
  276.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement