Team 3 Members

  1. Gurram Manoj Reddy
  2. Kolloju Nagarjuna
  3. Phand Atharva Hemant
  4. Pitta Venkat

Summary

This tutorial presents a comprehensive approach to backtesting a trend-following trading strategy on S&P 500 energy sector stocks using daily OHLC (Open, High, Low, Close) data. Our strategy is based on a two-trend system that identifies and capitalizes on short-term and long-term market movements. The backtesting period extends from January 2022 through December 2023, with a starting investment capital of $100,000. This strategy permits both long and short positions, enabling flexibility in response to market trends.

Performance evaluation of the backtested strategy includes measures such as total return, Sharpe ratio, maximum drawdown, and win-loss ratio, providing a holistic view of the strategy’s effectiveness and risk-adjusted returns. Additionally, the tutorial details the optimization process for selecting the best parameters for the moving averages and other parameters ensuring the strategy is finely tuned for the specific characteristics of the energy sector.

Following the initial backtesting, the strategy is applied to another industrial sector, Health Care to assess its versatility and performance in different market conditions. Furthermore, a retrospective analysis is conducted for the period January 2019 through December 2020 to compare the strategy’s performance during different market phases. This comparison reveals insights into the strategy’s adaptability and potential areas for adjustment in response to varying market environments.

The tutorial concludes with key takeaways, emphasizing the importance of trend analysis, risk management, and the adaptability of trading strategies across different sectors and time periods.

Learning Outcomes:

  1. Understanding of Financial Market Data Manipulation: Learners will gain hands-on experience in manipulating and analyzing financial market data, focusing on OHLC (Open, High, Low, Close) data and moving averages, which are crucial for trend analysis.

  2. Application of Technical Analysis in Trading: The script applies fundamental concepts of technical analysis, such as moving averages, to generate buy or sell signals. This provides practical insights into how traders can use historical price data to make informed decisions.

  3. Development of Trading Strategies: By following this script, learners will understand the steps involved in developing and testing a trading strategy. This includes setting initial capital, defining trading signals, managing positions, and implementing risk management rules.

  4. Backtesting and Optimization: The script demonstrates how to backtest a trading strategy against historical data to evaluate its performance. This is vital for understanding the strategy’s potential profitability and risk before applying it in live trading.

  5. Risk Management: Through the implementation of maximum trade value and maximum daily trades, learners will appreciate the importance of risk management in trading. This includes how to size positions and when to exit trades to minimize losses.

  6. Performance Evaluation: The script calculates key performance metrics such as total return, Sharpe ratio, and maximum drawdown. Learning how to evaluate these metrics is crucial for assessing the strategy’s effectiveness and comparing it to other strategies or benchmarks.

Steps:

This tutorial breaks down the process of creating and testing a trading strategy into five clear steps, making it easier to follow and implement.

1. Trading Strategy Definition: We start by clearly laying out our trading strategy. This means clearly stating what we want to achieve, the signals that will tell us when to buy or sell, and the rules for starting and ending trades.

2. Setting Parameters: Next, we detail our strategy’s goals, risk levels, and other important benchmarks like maximum value per trade and maximum trades per day.

3. Generating Indicators : We generate technical indicators, Fast Moving Average (FMA) and Slow Moving Average (SMA), enabling the identification of trend-based trading signals.

4. Generating Signals : We then create a system to find buy or sell signals from past market data. This involves analyzing historical trends that match our strategy’s criteria to identify the best times to trade.

5. Applying Strategy Rules: Here, we turn the theoretical aspects of our strategy into actual trading actions. This means translating when and how we’ll enter and exit trades into concrete steps, ensuring our trades stick to our original plan.

6. Managing the Portfolio: This step focuses on keeping a close eye on our investments, making sure everything is accounted for and managed properly.

7. Reviewing Performance: The last step involves regularly checking how our trades are doing, and evaluating if our strategy meets our goals.

Further Exploration:

Conclusion: By simplifying this process into manageable steps, this tutorial offers a straightforward path to developing, implementing, and refining a trading strategy.

1. Trading Strategy Definition

The trend strategy is designed for trading within the S&P 500 energy sector stocks. It utilizes moving averages as indicators to capture market trends and guide trading decisions.

1. Indicator Generation:

  • Fast Moving Average (FMA): A 20-day moving average that reacts quickly to price changes, indicating short-term price trends.
  • Slow Moving Average (SMA): A 40-day moving average that smoothens out price data over a longer period, showing longer-term price direction.

The use of two moving averages helps to identify the momentum and direction of stock prices by comparing short-term price movements to longer-term trends.

2. Trading Signal Criteria and Trade Execution:

We now see how positions are opened, managed, and closed:

Opening Positions:

  1. Long Positions (Buying):
    • Entry Signal: Initiate a buy order when the current stock price moves above both the Fast Moving Average (FMA) and Slow Moving Average (SMA).
    • Rationale: Crossing above both moving averages suggests a strong upward trend, indicating a potential for profit from rising prices.
  2. Short Positions (Selling Short):
    • Entry Signal: Enter a sell short order when the current stock price drops below both the FMA and SMA.
    • Rationale: Falling below both averages signals a strong downward trend, presenting an opportunity to profit from declining stock prices.

Holding and Monitoring Positions:

  • After entering a position, it is held until the exit criteria, based on moving averages, signal a potential change in the trend direction.

Closing Positions:

  1. Exiting Long Positions:
    • Exit Signal: Close out (sell) the long position when the current price falls below either the FMA or SMA.
    • Rationale: Dropping below either moving average may indicate the upward trend is losing momentum, warranting an exit to protect profits or minimize losses.
  2. Exiting Short Positions:
    • Exit Signal: Cover (buy back) the short position when the current price rises above either the FMA or SMA.
    • Rationale: Rising above either average suggests the downward trend may be weakening, prompting an exit to capture gains from the short sale or to reduce potential losses.

2. Setting Parameters

The above R script snippet is setting up an environment for financial data analysis by loading libraries for technical analysis and visualization. It also includes steps to define the working directory, and clear the workspace to start with a clean slate.

We then load a 5-year financial dataset and sector information, specifically focusing on the Energy sector’s stocks from 2021 to 2023. It sets the trading strategy’s initial capital at $100,000, limits trades to $5,000 each, and restricts to 8 trades per day.

3. Generating Indicators :

In lines (40-56), the genIndicators function prepares technical indicators for a specific stock symbol. It selects the stock’s data (42), converts it for time series calculations (43), and computes the fast and slow moving averages (46-47). It then filters the data to start from January 1, 2022 (53) for backtesting, resets row names (54), and then returns the data frame with added indicators (55-56).

Below are snapshots displaying the indicators via dataframe and graph (APA and MPC stock):

4. Generating Signals:

We select the data filtering by stock , converting it to a time series format for easier analysis (66), and creates two signals: “cross.upper” when the closing price is above both the fast and slow moving averages, indicating a bullish trend (68-70), and “cross.lower” when below, signaling a bearish trend (71-73).

In lines (75-90), We define trading signals for a stock symbol. It creates a “cross.trendup” signal for when the closing price is above either moving average, suggesting a potential upward trend (75-77), and a “cross.trenddn” signal for when the closing price is below at least one, indicating a possible downward trend (78-80).

Below is a snapshot displaying the signals:

5. Applying Strategy Rules:

Lines (199-212) applyRules function, performs two main tasks: it first evaluates and closes any existing positions that meet the strategy’s sell criteria, then it identifies and opens new positions based on the buy criteria. Later, we update the total equity after accounting for the profits or losses from closed positions and returns the current state of the portfolio, including open positions and available cash.

The R function closePositions in lines (101-116) manages the closure of trading positions. If there are any open positions, it determines which ones to close based on the day’s trading signals. It handles both long and short positions separately, closing long positions when a downtrend signal is detected and short positions when an uptrend signal is present.

The R code in lines (117-127) processes the final steps in closing trading positions. If there are any positions that have been closed, it calculates the cash realized from each, the profit or loss, and updates the total cash balance accordingly. If no positions have been closed, it sets the list of closed positions to NULL. Finally, the function returns a list with the details of the closed positions and the updated cash balance.

In openPositions function:

In lines (168-191), the openPositions function finalizes the process of opening new trading positions. It starts by assigning buy or sell prices to the newly opened positions, depending on whether they are long or short. The function then limits the number of trades to the maximum daily allowed, ensuring it does not exceed the set parameter maxdaytrades. It calculates the trade amount, distributing the available equity evenly across all trades, and adjusts the position sizes based on this calculation. The cash spent on opening the positions is accumulated to update the total cash balance. If no positions are opened, it sets the opened variable to NULL. Finally, the function returns a list that includes the opened positions and the remaining cash after these new positions have been taken.

6. Managing the Portfolio:

We manage the daily portfolio through a loop that iterates over each trading day. It calls applyRules (line 299) to decide on opening or closing positions and adjusts the cash balance based on these trades (line 302). On days with open positions, it calculates the current market value of these holdings (lines 304-308) and updates the portfolio’s value accordingly. The portfolio value for each day is determined by combining the value of open positions with the current cash balance (line 312). If no positions are open, the portfolio value for that day is recorded as zero (line 310).

7. Reviewing the performance:

The portfolioStats function, calculates various statistics to evaluate trading performance. It determines the number of unique trading days, total trades, and distinguishes between long and short trades. It computes the percentage of winning trades, average returns for long and short positions separately, and the overall percentage of profitable trades. Additionally, the function calculates cumulative returns, maximum returns, and maximum drawdown percentages to assess the risk and return profile of the trading strategy. It also calculates the longest drawdown period and the Sharpe ratio, which is a measure of risk-adjusted return.

1. Working of strategy:

Here’s a glimpse of our trading strategy’s outcomes for HAL stock, showcasing a successful example of both a long and a short trade.

The provided chart illustrates the application of our dual moving average crossover strategy on the stock price of HAL. In this strategy:

  • A Long Position is initiated when the stock’s price (represented by the black line) crosses above both the Fast Moving Average (FMA, in green) and the Slow Moving Average (SMA, in blue), indicating an uptrend. For instance, we see a “Buy” signal where the stock is bought at $23.14 when the price crosses above both moving averages.

  • The position is then Closed (sold) when the stock price drops below either moving average, suggesting the uptrend may be weakening. This is observed in the “Sell” transaction at $31.46.

  • Conversely, a Short Position is entered when the stock price falls below both the FMA and SMA, signaling a downtrend. This is marked by “Short” at $38.65.

  • The short position is Covered (bought back) when the stock price rises above either moving average, implying the downtrend might be reversing, shown by “Cover” at $38.08.

2. Performance Analysis:

The chart shows three different metrics: Cumulative Return, Max Return, and Portfolio Return. The black line representing Cumulative Return likely shows the compounded total return of the portfolio over the observed period. The red line for Max Return indicates the highest value the portfolio has reached, a useful measure for understanding the portfolio’s peak performance. The blue line, showing Portfolio Return, might represent the actual return of the portfolio at the end of the period.

The performance summary suggests that the trading strategy resulted in a total of 1275 trades. Out of these, 679 were long trades with a win rate of approximately 54.63%, and 596 were short trades with a slightly lower win rate of around 54.19%. The average return on long trades was about 2.49%, while for short trades, it was slightly lower at around 1.94%. Overall, the strategy won 54.43% of the time.

The cumulative return of 2.09 indicates that the portfolio more than doubled over the period tested. The mean daily return was very low, suggesting that while the strategy was profitable, the profits on any given day were quite small, which is typical for high-frequency trading strategies that don’t hold positions for long.

The Sharpe ratio of 2.33 is quite high, which often indicates a good risk-adjusted return. However, the maximum drawdown of -6.004 suggests that at one point, the portfolio lost more than 6% of its value from the previous high, which might be acceptable given the overall returns but still represents a significant risk. The maximum drawdown period of 36 days shows that the longest losing streak lasted just over a month, which should be manageable in the context of the overall performance.

Considering the initial equity was set at $100,000 with a maximum trade value of $5,000 and a limit of 8 trades per day, the strategy seems to have managed risk well, not committing more than 5% of the total capital to any single trade and keeping the number of daily trades to a conservative level. The positive Sharpe ratio and overall profitability indicate that the strategy could be effective for managing a similar-sized portfolio within the constraints set.

8. Trying Out Different Settings

We experimented with various settings to see how changes might improve our strategy. Below are the results for the hyper parameters we tried:

Max Val per Trade Max Trades per day FMA size SMA size Cum. Return Sharpe Ratio
5000 8 15 30 2.09 2.33
5000 8 15 45 1.94 2.06
9000 20 15 30 2.80 2.43
5000 8 20 40 1.74 1.66
5000 10 20 40 1.68 1.57

Key Observations:

9. Trying On Other Sector

We have applied the best settings from our previous experiments with trading parameters to a new sector (Utilties) and here are the performance results of the trading strategy.

  1. Total Trades: 3900 trades were executed.
  2. Long Trades: Out of the total, 2617 were long trades.
    • Percentage Winning Long: 53.61% of the long trades were profitable.
    • Average Return Long: The average return from long trades was approximately 0.9458% per trade.
  3. Short Trades: 1283 were short trades.
    • Percentage Winning Short: 54.01% of the short trades were profitable.
    • Average Return Short: The average return from short trades was approximately 1.0524% per trade.
  4. Overall Winning Percentage: 53.74% of all trades were profitable.
  5. Cumulative Return: The cumulative return of the strategy was 2.676174.
  6. Mean Return: The mean return per trade was approximately 0.02004%.
  7. Sharpe Ratio: The strategy achieved a Sharpe Ratio of 3.652418, which is quite high and indicates a good risk-adjusted return.
  8. Maximum Drawdown: The maximum drawdown experienced by the strategy was -6.599879%.
  9. Maximum Drawdown Period: The maximum drawdown lasted for 32 periods.

Analysis of Results:

  • Overall Profitability: The overall winning percentage and cumulative return suggest the strategy has been profitable over the tested period.
  • Sharpe Ratio: A Sharpe Ratio above 3 is considered excellent, suggesting that the excess return per unit of risk taken is high. This is a strong indicator of a good strategy, assuming the risk-free rate used in the calculation is appropriate for the context.

The results suggests a promising strategy for the health care sector, making our strategy robust.