Saturday, October 5, 2024

grse optimization to find BRs

 To optimize the buy and sell conditions to create a smoother equity curve, we can employ several techniques. One possible approach is to tune the breakout and breakdown conditions using optimization methods such as grid search, genetic algorithms, or optimization libraries. We'll explore how to adjust the conditions for a better risk-adjusted return, such as:

  • Varying the breakout threshold (currently set at 3%).
  • Modifying the closing percentage range in the upper 30%.
  • Adjusting the breakdown threshold (currently set at -3%).

Approach:

  1. Optimization setup: We can use an optimization library such as DEoptim (Differential Evolution), or a simple grid search to optimize the thresholds.
  2. Objective: Minimize the standard deviation (volatility) of the equity curve while maximizing the total returns. This will smooth the equity curve.
  3. Optimization of buy/sell conditions: Tune the breakout threshold (currently 3%) and breakdown threshold (currently -3%) to achieve a better trade-off between return and risk. 
  4. Optimization using DEoptim:

    • We define a function trading_strategy() that calculates the return and volatility of the strategy based on input parameters.
    • The parameters being optimized are:
      • breakout_threshold: The percentage change threshold to buy (currently set at 3%).
      • breakdown_threshold: The percentage change threshold to sell (currently set at -3%).
      • upper_percentage: The percentage of the day range within which the stock must close to trigger a breakout.
    • The objective of the optimization is to minimize volatility and maximize returns, which leads to a smoother equity curve.
  5. Optimized Conditions:

    • After optimization, the best values for the breakout threshold, breakdown threshold, and upper percentage are used to run the strategy.
  6. Plot and Output:

    • The plot displays the optimized buy and sell signals on the price chart and the smoother equity curve based on the optimized conditions.
  7. Customization:

    You can adjust the upper/lower bounds in lower_bounds and upper_bounds to explore different ranges of thresholds. The DEoptim algorithm can also be replaced with grid search or another optimization method if desired.



# Required Libraries

install.packages("DEoptim")


library(quantmod)

library(DEoptim)  # For optimization

library(dplyr)

library(ggplot2)


# Step 1: Download GRSE.NS data

symbol <- "GRSE.NS"

getSymbols(symbol, from = "2010-01-01", to = Sys.Date())

grse_data <- data.frame(date = index(GRSE.NS), coredata(GRSE.NS))


# Step 2: Define the function for the trading strategy

trading_strategy <- function(params) {

  breakout_threshold <- params[1]  # Buy on breakout threshold

  breakdown_threshold <- params[2]  # Sell on breakdown threshold

  upper_percentage <- params[3]     # Upper day range percentage

  

  # Calculate breakout and breakdown conditions based on parameters

  grse_data <- grse_data %>%

    mutate(

      perc_change = (GRSE.NS.Close - lag(GRSE.NS.Close)) / lag(GRSE.NS.Close) * 100,

      day_range = GRSE.NS.High - GRSE.NS.Low,

      upper_condition = GRSE.NS.High - GRSE.NS.Close <= upper_percentage * day_range,

      breakout = ifelse(perc_change >= breakout_threshold & upper_condition, TRUE, FALSE),

      breakdown = ifelse(perc_change <= breakdown_threshold, TRUE, FALSE)

    )

  

  # Step 3: Trading strategy: Buy on breakout, sell on breakdown

  trades <- data.frame(buy_date = as.Date(character()), buy_price = numeric(),

                       sell_date = as.Date(character()), sell_price = numeric(), 

                       return = numeric(), stringsAsFactors = FALSE)

  

  position_open <- FALSE

  capital <- 100000  # Initial capital

  equity_curve <- rep(capital, nrow(grse_data))

  

  for (i in 2:nrow(grse_data)) {

    # Skip if breakout or breakdown is NA

    if (is.na(grse_data$breakout[i]) | is.na(grse_data$breakdown[i])) next

    

    # Buy on breakout

    if (grse_data$breakout[i] && !position_open) {

      buy_price <- grse_data$GRSE.NS.Close[i]

      position_open <- TRUE

    }

    

    # Sell on breakdown

    if (position_open && grse_data$breakdown[i]) {

      sell_price <- grse_data$GRSE.NS.Close[i]

      return_trade <- (sell_price - buy_price) / buy_price

      capital <- capital * (1 + return_trade)

      position_open <- FALSE

    }

    

    # Update equity curve

    equity_curve[i] <- capital

  }

  

  # Return objective to minimize: negative total return and volatility

  total_return <- (capital - 100000) / 100000

  volatility <- sd(diff(equity_curve[equity_curve > 0])) / mean(equity_curve)

  # Minimize the negative of total return and volatility (for a smoother curve)

  return(-total_return + volatility)

}


# Step 4: Use DEoptim for optimization

lower_bounds <- c(1, -5, 0.1)  # Lower bounds for breakout, breakdown, and upper_percentage

upper_bounds <- c(5, -1, 0.5)  # Upper bounds for breakout, breakdown, and upper_percentage


# Run optimization

optim_results <- DEoptim(trading_strategy, lower = lower_bounds, upper = upper_bounds, 

                         control = list(itermax = 50))


# Extract optimized parameters

best_params <- optim_results$optim$bestmem

breakout_threshold <- best_params[1]

breakdown_threshold <- best_params[2]

upper_percentage <- best_params[3]


# Step 5: Run the optimized trading strategy and plot results

grse_data <- grse_data %>%

  mutate(

    perc_change = (GRSE.NS.Close - lag(GRSE.NS.Close)) / lag(GRSE.NS.Close) * 100,

    day_range = GRSE.NS.High - GRSE.NS.Low,

    upper_condition = GRSE.NS.High - GRSE.NS.Close <= upper_percentage * day_range,

    breakout = ifelse(perc_change >= breakout_threshold & upper_condition, TRUE, FALSE),

    breakdown = ifelse(perc_change <= breakdown_threshold, TRUE, FALSE)

  )


# Trading strategy: Buy on breakout, sell on breakdown

trades <- data.frame(buy_date = as.Date(character()), buy_price = numeric(),

                     sell_date = as.Date(character()), sell_price = numeric(), 

                     return = numeric(), stringsAsFactors = FALSE)


position_open <- FALSE

capital <- 100000  # Initial capital

equity_curve <- data.frame(date = grse_data$date, equity = capital)


for (i in 2:nrow(grse_data)) {

  # Skip if breakout or breakdown is NA

  if (is.na(grse_data$breakout[i]) | is.na(grse_data$breakdown[i])) next

  

  # Buy on breakout

  if (grse_data$breakout[i] && !position_open) {

    buy_price <- grse_data$GRSE.NS.Close[i]

    buy_date <- grse_data$date[i]

    position_open <- TRUE

  }

  

  # Sell on breakdown

  if (position_open && grse_data$breakdown[i]) {

    sell_price <- grse_data$GRSE.NS.Close[i]

    sell_date <- grse_data$date[i]

    return_trade <- (sell_price - buy_price) / buy_price

    capital <- capital * (1 + return_trade)

    trades <- rbind(trades, data.frame(buy_date = buy_date, buy_price = buy_price,

                                       sell_date = sell_date, sell_price = sell_price, 

                                       return = return_trade))

    position_open <- FALSE

  }

  

  # Update equity curve

  equity_curve$equity[i] <- capital

}


# Step 6: Plot the trades and equity curve

# Plot trades on price chart

ggplot(grse_data, aes(x = date, y = GRSE.NS.Close)) +

  geom_line() +

  geom_point(data = trades, aes(x = buy_date, y = buy_price), color = "green", size = 3, shape = 17) +

  geom_point(data = trades, aes(x = sell_date, y = sell_price), color = "red", size = 3, shape = 18) +

  ggtitle("GRSE.NS Price with Optimized Breakout Buy (Green) and Breakdown Sell (Red)") +

  xlab("Date") + ylab("Price") +

  theme_minimal()


# Plot equity curve

ggplot(equity_curve, aes(x = date, y = equity)) +

  geom_line(color = "blue") +

  ggtitle("Equity Curve (Optimized Compounded)") +

  xlab("Date") + ylab("Equity") +

  theme_minimal()


# Display trades table

print(trades)


No comments:

Post a Comment

Optimized Values

 RVNL