R and money game: golden cross 1

Near the double 11, I found that I was really poor, very poor, very poor

Poverty is a catalyst for progress. So I think about how to play the game of making money in my spare time. After all, even if it is destined to make leeks, it is also necessary to make an intellectual and ideal leek.

The first model to play is the golden cross of average in stock trading.

As a foundation, chives must have heard of the golden cross principle of the average line, that is, when the short-term moving average line breaks through the long-term moving average line upward, it indicates that the trend is rising and suitable for buying; on the contrary, if the short-term moving average line breaks through the long-term moving average line downward, it indicates that the trend is bearish and suitable for selling.

So does the trading principle that leeks all know really help you make money? Let's take Ping An of China as an example (in fact, it's still awkward to choose A-share analysis, in case you can't make money anyway...) Simply verify the modeling.

Required Packages

library(quantmod)
library(ggplot2)
library(scales)


Get Data

First, we download the stock price data using quantmod package. The stock code can be found in Yahoo Finance Check it out.

stock_code <- "601318.SS"
start <- as.Date("2018-01-01")
end <- as.Date("2020-01-01")
stock <- getSymbols(stock_code, from=start, auto.assign=FALSE)
names(stock) <- c("Open", "High", "Low", "Close", "Volume", "Adjusted")
stock <- stock[paste(start, end, sep='/')]$Close


Calculate Moving Average

Moving average can be divided into simple moving average (SMA), weighted moving average (WMA) and exponential moving average (EMA).

We usually choose the exponential moving average. Because the moving average will lag behind the real-time trend of the stock price to some extent, and the newer the index moving average is in the calculation, the greater the weighted proportion of the data is, and it can reflect the change of the stock price faster.

ma <- function(data, mas=c(5, 20, 60)) {
  ma_data <- data
  for(m in mas) {
    ma_data <- merge(ma_data, EMA(data, m))
  }
  ma_data <- na.locf(ma_data, fromLast = TRUE)
  names(ma_data) <- c('Value', paste('MA', mas, sep=''))
  return(ma_data)
}

We can draw the calculation results into a graph:


Get Trading Signals

Take the 5-day and 20 day moving average as an example, we can find the trading point according to the golden cross principle of the average, that is, when the 5-day moving average of a certain day is greater than the 20 day moving average, it is a buy; otherwise, when the 5-day moving average of a certain day is less than the 20 day moving average, it is a sell.

We can group data. When the 5-day average is greater than the 20 day average, it is "buy"; when the 5-day average is less than the 20 day average, it is "sell" Among them, "buy" and "sell" appear at an indefinite interval. Then, the first "buy" in each paragraph is a buy, and the first "sell" is a sell. In order to calculate the profit conveniently, we set buying as the first transaction and selling as the last transaction.

If we have been following the principle of average gold cross, there are 30 transactions (total sales) since January 1, 2018.

get_signals<- function(data, mas_1=5, mas_2=20) {
  if(mas_1 == 0)
    ma_name_1 <- "Value"
  else
    ma_name_1 <- paste('MA', mas_1, sep='')
  ma_name_2 <- paste('MA', mas_2, sep='')
  ma_data <- data[, c("Value", ma_name_1, ma_name_2)] #please calculate ma value before and get a dataframe like the section above
  down_data <- ma_data[which(ma_data[, c(ma_name_1)] > ma_data[, c(ma_name_2)]), c("Value")]
  up_data <- ma_data[which(ma_data[, c(ma_name_1)] < ma_data[, c(ma_name_2)]), c("Value")]
  result <- merge(down_data, up_data)
  names(result) <- c("buy", "sell")
  result <- fortify(result, melt=TRUE)
  result<- result[-which(is.na(result$Value)),]
  signals <- result[order(result$Index),]
  signals$Signal <- ifelse(signals$Series == "buy", 1, 0)
  signals$Signal <- c(ifelse(signals$Series[1] == "buy", 1, -1),diff(signals$Signal))
  signals <- signals[which(signals$Signal != 0),]
  #delete odd rows
  if(nrow(signals)%%2 == 1) {
    if(signals$Series[1] == "buy")
      signals <- signals[-c(nrow(signals)),]
    else
      signals <- signals[-c(1),]
  }
  if(signals$Series[1] == "sell") {
    signals <- signals[-c(nrow(signals)),]
    signals <- signals[-c(1),]
  }
  return (signals)
}


Mock Trading

We have found out the trading points above, but in fact, the purpose of finding out these possible historical trading points is to know whether we can make money if we strictly follow these trading points?

Here we can simulate the process of the transaction:

Suppose we have 10000 principal, full position entry, and the transaction rate is 0.3%

mock_trading <- function(signals, capital=10000, position=1, fee=0.003){
  amount <- 0
  cash <- capital * position
  ticks <- data.frame()
  
  for(ii in 1:nrow(signals)){
    row <- signals[ii,]
    if(row$Series == "buy") {
      amount <- floor((cash/(1+fee))/row$Value)
      cash <- cash - amount * row$Value - (amount * row$Value) * fee
    }
    if(row$Series == "sell") {
      cash <- cash + amount * row$Value - (amount * row$Value) * fee
      amount <- 0
    }
    row$cash <- cash
    row$amount <- amount
    row$asset<- cash + amount * row$Value  
    row$fee <- (amount * row$Value) * fee
    ticks<-rbind(ticks, row)
  }
  ticks$diff <- c(0, diff(ticks$asset))
  
  rise <- ticks[c(which(ticks$diff > 0)-1, which(ticks$diff > 0)),]
  rise <- rise[order(rise$Index),]
  fall <- ticks[c(which(ticks$Series=="sell" & ticks$diff < 0)-1, which(ticks$Series=="sell" & ticks$diff < 0)),]
  fall <- rise[order(fall$Index),]

  return(list(
    ticks = ticks,
    rise = rise,
    fall = fall
  ))
}

If we strictly follow the golden cross principle of the average line, after two years of ups and downs in the stock market, our principal is only 7962.18, with a loss of 2037.82, while the transactions that make money are only six times (total transactions).

We can see that we lost a lot in the early trading by drawing a graph of asset and stock price curves. On the one hand, the trend of the stock price is indeed falling (as the leeks know after 2018), is there any reason for the wrong trading choice?

When we draw the profit and loss trading separately, we can see that the loss trading is still fluctuating when the stock price has not yet formed a trend, such as 2018-08 and 2018-10-2018-11. Therefore, from the data point of view, the golden cross principle of average can only guide the stock prices that have formed a trend.

However, we can also be optimistic that as long as we can avoid the shock period, the golden cross principle of the average can help us make a small profit. But today I don't know about tomorrow. It's hard to see whether a certain intersection is on the trend with the naked eye.

What indicators can we introduce to avoid the shock period? We will continue to discuss it later.

Tags: R Language less

Posted on Thu, 07 Nov 2019 13:30:23 -0800 by lanas