How I Got the AI to Create, Code, and Backtest a Quant Portfolio in Python Without Writing a Single Line of Code!
I wanted to explore the new capabilities of the Advanced Data Analysis module, available in the GPT-4 options. I provided ChatGPT with historical daily prices for SPY, TLT, and GLD, and asked it to devise a trading strategy with a strong Sharpe ratio. Simple enough, right?
Here’s the prompt I gave to GPT, enabled with Beta Advanced Data Analysis:
I allowed it the freedom to choose one or all of the instruments and asked what the next steps would be. It responded with a list of Preliminary Steps.
It proposed starting by loading the data, to which I agreed.
A small window then appeared, stating “Working.” What was happening in the background? The AI was writing and executing Python code!
ChatGPT read the CSV data into a Pandas DataFrame. What’s a Pandas DataFrame? Well, thanks to AI, you don’t need to know (although you really should)!
Once it finished, it informed me about the data format, dates, etc., and suggested next steps:
Data Alignment and Feature Engineering! “Sure, go for it,” I said.
It proceeded to run a script that determined when each price history started, aligned the data, and calculated two simple moving averages.
Next steps included Correlation Analysis, Hypothesis Generation, and Initial Backtesting. “Not .bad..”, I thought to myself.
It tried to write code to generate the correlation but encountered an error while creating the heat-map chart. It apologised and asked if displaying the correlation table alone would suffice. I agreed. So it gave me a table of correlations, and asked whether to move to the next steps.
Upon inspecting the table, I realized that the correlation numbers didn’t make sense. For instance, SPY and TLT had a correlation of 0.791? Clearly, it had run a correlation analysis on all the data. What was needed was a 1-month average correlation. Coding that in Python? No need!
I pointed out the issue, and it responded, “Good catch!” It then suggested using a rolling correlation analysis.
“Yes, I would prefer to see the average 1-month correlation,” I replied.
It showed me the updated correlation numbers: negative for SPY/TLT and neutral for SPY/GLD, which sounded about right. The Python code it used for this was surprisingly simple:
# Calculate the 1-month (approx. 21 trading days) rolling correlation
rolling_correlation = merged_data[['Adj Close_SPY', 'Adj Close_TLT', 'AdjClose_GLD']].rolling(window=21).corr(pairwise=True)
# Take the mean of the rolling correlations to get the average 1-month correlation average_rolling_correlation = rolling_correlation.groupby(level=1).mean()
It then asked if I wanted to proceed to formulate trading rules. “Yes!” I exclaimed.
It proposed three simplistic strategies:
- A moving average 50/200 SMA crossover for SPY.
- A TLT ‘hedge’ strategy based on the TLT/SPY correlation.
- A GLD ‘diversification’ strategy based on buying GLD when SPY and TLT underperformed.
I agreed to proceed, one strategy at a time.
It clearly stated the rules for the 500/200 SMA crossover strategy for SPY and executed the Python code.
It returned the final portfolio value and return. Below is the python code it wrote and executed:
# Initialize variables for backtesting the SMA crossover strategy for SPY initial_investment = 10000 # USD cash = initial_investment stock_quantity = 0 buy_price = 0 # Price at which the stock was bought portfolio_value =  # To store the value of the portfolio at each time step # Flags to indicate the state of the portfolio in_position = False # True if currently holding the stock # Loop through the SPY data to simulate the trading for i in range(len(spy_data_aligned)): row = spy_data_aligned.iloc[i] date = row['Date'] price = row['Adj Close'] sma_50 = row['SMA_50'] sma_200 = row['SMA_200'] # Skip rows where the SMA values are not available if pd.isna(sma_50) or pd.isna(sma_200): portfolio_value.append(cash) continue # Check for Buy signal if sma_50 > sma_200 and not in_position: # Buy the stock stock_quantity = cash // price # Floor division to get the integer number of stocks that can be bought buy_price = price cash -= stock_quantity * buy_price # Deduct the investment from cash in_position = True # Check for Sell signal if sma_50 < sma_200 and in_position: # Sell the stock cash += stock_quantity * price stock_quantity = 0 in_position = False # Calculate the current value of the portfolio current_portfolio_value = cash + stock_quantity * price portfolio_value.append(current_portfolio_value) # Calculate the final returns final_portfolio_value = portfolio_value[-1] total_return = (final_portfolio_value - initial_investment) / initial_investment * 100 # in percentage total_return, final_portfolio_value
I asked it to plot the equity curve and compare it against SPY as a benchmark. All good.
I continued in the same manner with the TLT and GLD strategies.
After finalising the three strategies, I asked ChatGPT to allocate a piece of the portfolio to each strategy, based on it’s Sharpe ratio. Despite some hiccups, it constructed a portfolio with a combination of the three rule-based strategies, allocating more to the best ones.. Overall, an impressive feat for a text-based chatbot!
To be honest it surprised me! Using ChatGPT equipped with the Advanced Data Analysis tool is akin to having a junior coder sitting right beside you. It’s incredibly useful for tackling trading questions that might be tedious to code but are easy to understand conceptually.
For instance: “Find out what would happen if you bought SPY shares each Monday and sold them on a Tuesday for the past 10 years”. It is also very useful for running sophisticated analysis using Python libraries that are time-consuming to learn. Like SciPy to cluster ETFs based on their correlation.
For more advanced analysis it needs an experienced operator/coder. It makes mistakes that are difficult to spot and hard to debug as they are hidden away in code that is written as ‘language’ not as ‘logic’. When it gets too messy, writing the code from scratch can sometimes be easier.
This tool was not meant for backtesting trading strategies. Amazingly it does a great job with the basics.