Created
July 13, 2020 01:20
-
-
Save jaymon0703/7a36a05c3af8a3635e089695335aa302 to your computer and use it in GitHub Desktop.
macd_sig fun - silly maybe not so silly strategy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Simple MACD signal strategy | |
| # | |
| # blotter v 0.10.0 | |
| # quantstrat v 0.9.1739 | |
| # FinancialInstrument v 1.2.0 | |
| # Rblpapi v 0.3.4 | |
| # | |
| # | |
| # Author: Jasen | |
| ############################################################################### | |
| t1 <- Sys.time() | |
| options(width=81,continue=" ",digits=8) | |
| #options(error = recover) | |
| require(quantstrat) | |
| require(PerformanceAnalytics) | |
| require(quantmod) | |
| require(TTR) | |
| # require(Rblpapi) | |
| # blpConnect() | |
| # Set initial values | |
| initDate <- as.Date("1998-02-01") | |
| #startDate <- as.Date("2007-06-10") | |
| #bbgstartDate <- as.Date("2009-01-01") | |
| #endDate <- as.Date("2016-06-24") | |
| initEq <- 1000000 | |
| tradeSize <- initEq | |
| #initEq <- tradeSize*length(symbols) | |
| currency("USD") | |
| currency("EUR") | |
| symbols = c("XLF", "XLP", "XLE", "XLY", "XLV", "XLI", "XLB", "XLK", "XLU") | |
| #symbols = "XLI" | |
| for(symbol in symbols){ # establish trade-able instruments | |
| stock(symbol, currency="USD",multiplier=1) | |
| } | |
| getSymbols(symbols, src='yahoo', index.class=c("POSIXt","POSIXct"), from='1998-01-01') | |
| # Delete portfolio, account, and order book if they already exist | |
| rm.strat("macdX") | |
| suppressWarnings(rm("account.macdX","portfolio.macdX",pos=.blotter)) | |
| suppressWarnings(rm("order_book.macdX",pos=.strategy)) | |
| # Initialize portfolio and account | |
| initPortf("macdX", symbols=symbols, initDate=initDate) | |
| initAcct("macdX", portfolios="macdX", initDate=initDate, initEq=initEq) | |
| initOrders(portfolio="macdX", initDate=initDate) | |
| # set intial position limits | |
| posval<-initEq/length(symbols) | |
| for(symbol in symbols){ | |
| pos<-round((posval/first(getPrice(get(symbol)))[,1]),-2) | |
| addPosLimit("macdX",symbol,initDate, maxpos=pos,minpos=-pos) | |
| } | |
| print("setup completed") | |
| # Initialize a strategy object | |
| strat.macdX <- strategy("macdX") | |
| ATRperiod = 14 | |
| #one indicator (ok more than one indicator :)) | |
| strat.macdX <- add.indicator(strategy=strat.macdX, name="ATR", | |
| arguments=list(HLC=quote(HLC(mktdata)), n=ATRperiod), | |
| label="atrX") | |
| #MA parameters for short MACD | |
| fastMA = 12 | |
| slowMA = 26 | |
| signalMA = 9 | |
| maType="EMA" | |
| #MA parameters for short MACD | |
| longfastMA = 240 | |
| longslowMA = 520 | |
| longsignalMA = 180 | |
| # parameters for stop and position sizing | |
| nATR = 4 | |
| mper=30 | |
| nSMA = 200 | |
| strat.macdX <- add.indicator(strat.macdX, name = "MACD", | |
| arguments = list(x=quote(Ad(mktdata)), nFast=fastMA, nSlow=slowMA, nSig=signalMA, maType=maType), | |
| label='_shortper' | |
| ) | |
| strat.macdX <- add.indicator(strat.macdX, name = "MACD", | |
| arguments = list(x=quote(Ad(mktdata)), nFast=longfastMA, nSlow=longslowMA, nSig=longsignalMA, maType=maType), | |
| label='_longper' | |
| ) | |
| strat.macdX <- add.indicator(strat.macdX, name = "SMA", | |
| arguments = list(x=quote(Ad(mktdata)), n=nSMA), | |
| label='sma200' | |
| ) | |
| test <- applyIndicators(strat.macdX, mktdata=OHLC(NPN)) | |
| head(test) | |
| # # Jasen's custom indicator | |
| # macdtrend <- function(x=Cl(mktdata), nFast=fastMA, nSlow=slowMA, nSig=signalMA, maType=maType){ | |
| # m5 <- MACD(x, nFast, nSlow, nSig, maType) | |
| # m4 <- MACD(x[1:(nrow(x)-1)], nFast, nSlow, nSig, maType) | |
| # | |
| # if(m5*m4 > 0){ | |
| # macdtrend <- 1 | |
| # } else { | |
| # macdtrend <- 0 | |
| # } | |
| # return(macdtrend) | |
| # } | |
| #two signals | |
| JsigFormula <- function(label, data=mktdata, formula ,cross=FALSE, mper){ | |
| # Vijay's PAST/AAII/SIPRO example | |
| # fieldVals <- try(eval(parse(text=expression), data)) | |
| ret_sig=NULL | |
| ret_sig <- try(.xts(eval(parse(text=formula), as.list(data)),index=.index(data))) | |
| if(is.xts(ret_sig)){ | |
| if(isTRUE(cross)) ret_sig <- diff(ret_sig)==1 | |
| colnames(ret_sig)<-label | |
| } | |
| #return(ret_sig) | |
| #ret_sig <- ifelse(ret_sig == TRUE, FALSE, TRUE) # do this if you looking for short signal | |
| # ret_sig <- rollapply(ret_sig, 10, sum) | |
| # return(ret_sig) | |
| ret_sig[is.na(ret_sig)] <- 0 | |
| ret_sig[mper:length(ret_sig)] <- rollsum(ret_sig, mper) | |
| return(ret_sig) | |
| } | |
| strat.macdX <- add.signal(strat.macdX, name="JsigFormula", | |
| arguments=list(columns=c("signal._shortper", | |
| "signal._longper"), | |
| formula="(signal._shortper > 0) & (signal._longper > 0)", | |
| cross=FALSE, mper=30), label="ENTRY") | |
| # SMA200 signal | |
| strat.macdX <- add.signal(strat.macdX, name="sigComparison", | |
| arguments=list(columns=c("Adjusted","sma200"), | |
| relationship="lte"), | |
| label="Cl.lte.sma200") | |
| testSignals <- applySignals(strat.macdX, mktdata=OHLC(NPN)) | |
| head(test) | |
| # strat.macdX <- add.signal(strat.macdX, name="sigFormula", | |
| # arguments=list(columns=c("signal._shortper", | |
| # "signal._longper"), | |
| # formula="(signal._shortper > 0) & (signal._longper > 0)", | |
| # cross=FALSE), label="ENTRY") | |
| # strat.macdX <- add.signal(strat.macdX, name="sigFormula", | |
| # arguments=list(columns=c("signal._shortper", | |
| # "signal._longper"), | |
| # formula="(signal._shortper > 2) & (signal._longper > 0)", | |
| # cross=TRUE), label="ENTRY2") | |
| # strat.macdX <- add.signal(strat.macdX,name="sigThreshold", | |
| # arguments = list(column="signal._", | |
| # relationship="gt", | |
| # threshold=0, | |
| # cross=TRUE), | |
| # label="signal.gt.zero" | |
| # ) | |
| # | |
| # strat.macdX <- add.signal(strat.macdX,name="sigThreshold", | |
| # arguments = list(column="signal._shortper", | |
| # relationship="lt", | |
| # threshold=0, | |
| # cross=FALSE), | |
| # label="signal.lt.zero" | |
| # ) | |
| #### | |
| # add rules | |
| # orderqty | |
| # ORDQTY <- function(data, timestamp, orderqty, ordertype, orderside, | |
| # portfolio, symbol, prefer="Close", | |
| # integerQty=TRUE, | |
| # ...) { | |
| # if(prefer=="Close") { | |
| # price <- as.numeric(Cl(mktdata[timestamp,])) | |
| # } else { | |
| # price <- as.numeric(Op(mktdata[timestamp,])) | |
| # } | |
| # dollarsToTransact <- initEq * 0.02 | |
| # if (orderside=="short") { | |
| # qty <- -dollarsToTransact / price | |
| # } else { | |
| # qty <- dollarsToTransact / price | |
| # } | |
| # if(integerQty) { | |
| # qty <- trunc(qty) | |
| # } | |
| # return(qty) | |
| # } | |
| ORDQTY2 <- function(data, timestamp, orderqty, ordertype, orderside, | |
| portfolio, symbol, prefer="Open", | |
| integerQty=TRUE, | |
| ...) { | |
| if(getPosQty("macdX", symbol, timestamp) == 0){ | |
| if(prefer=="Close") { | |
| price <- as.numeric() | |
| } else { | |
| price <- as.numeric(Op(mktdata[timestamp,])) | |
| } | |
| sharesToTransact <- (initEq * 0.01) / (nATR * mktdata$atr.atrX[timestamp]) | |
| if (orderside=="short") { | |
| #qty <- -dollarsToTransact / price | |
| qty <- -sharesToTransact | |
| } else { | |
| qty <- sharesToTransact | |
| } | |
| if(integerQty) { | |
| qty <- trunc(sharesToTransact) | |
| } | |
| return(qty) | |
| } | |
| } | |
| # entry | |
| # strat.macdX <- add.rule(strat.macdX,name='ruleSignal', | |
| # arguments = list(sigcol="signal.gt.zero", | |
| # sigval=TRUE, | |
| # osFUN = ORDQTY, | |
| # ordertype='market', | |
| # orderside='long', | |
| # threshold=NULL), | |
| # type='enter', | |
| # label='enter', | |
| # storefun=FALSE | |
| # ) | |
| strat.macdX <- add.rule(strat.macdX,name='ruleSignal', | |
| arguments = list(sigcol="ENTRY", | |
| sigval=mper, | |
| #tradeSize = initEq * 0.2 / quote(mktdata$atr.atrX[timestamp]), | |
| #addPosLimit("macdX", symbol, timestamp, maxpos = tradeSize), | |
| osFUN = ORDQTY2, #osMaxPos, | |
| ordertype='market', | |
| orderside='long', | |
| threshold=NULL, | |
| prefer='Open'), | |
| #TxnFees = -(ORDQTY2 * quote(mktdata$Cl[timestamp]) * 0.01)), | |
| type='enter', | |
| label='enter', | |
| storefun=FALSE | |
| ) | |
| # strat.macdX <- add.rule(strat.macdX,name='ruleSignal', | |
| # arguments = list(sigcol="ENTRY2", | |
| # sigval=TRUE, | |
| # osFUN = ORDQTY, | |
| # ordertype='market', | |
| # orderside='long', | |
| # threshold=NULL, | |
| # prefer='Open'), | |
| # type='enter', | |
| # #type='chain', | |
| # #parent='enter', | |
| # label='enter', | |
| # storefun=FALSE | |
| # ) | |
| #alternatives for risk stops: | |
| # strat.macdX <- add.rule(strat.macdX,name='ruleSignal', | |
| # arguments = list(sigcol="ENTRY", | |
| # sigval=TRUE, orderqty='all', | |
| # ordertype='stoptrailing', | |
| # orderside='long', tmult=FALSE, threshold=quote(-2 * (mktdata$atr.atrX[timestamp])), orderset='exit2'), | |
| # type='chain', parent='enter', label='trailingexit') | |
| # strat.macdX <- add.rule(strat.macdX,name='ruleSignal', | |
| # arguments = list(sigcol="ENTRY", | |
| # sigval=TRUE, orderqty='all', | |
| # ordertype='stoptrailing', | |
| # orderside='long', tmult=FALSE, threshold=quote(-nATR * (mktdata$atr.atrX[timestamp])), orderset='exit2'), | |
| # type='chain', parent='enter', label='trailingexit') | |
| # exit | |
| strat.macdX <- add.rule(strat.macdX,name='ruleSignal', | |
| arguments = list(sigcol="Cl.lte.sma200", | |
| sigval=TRUE, | |
| orderqty='all', | |
| ordertype='market', | |
| orderside='long', | |
| threshold=NULL, | |
| prefer='Open'), | |
| type='exit', | |
| label='exit' | |
| ) | |
| testRules <- applyRules("macdX", "NPN", strat.macdX, mktdata=mktdata) | |
| #end rules | |
| #### | |
| out <- applyStrategy(strategy=strat.macdX, portfolios="macdX") | |
| updatePortf("macdX") | |
| updateAcct("macdX") | |
| updateEndEq("macdX") | |
| # chart.Posn(Portfolio="macdX",Symbol="AGL") | |
| # plot(add_MACD(fast=fastMA, slow=slowMA, signal=signalMA,maType="EMA")) | |
| #look at the order book | |
| obook<-getOrderBook('macdX') | |
| # create custom theme | |
| myTheme<-chart_theme() | |
| myTheme$col$dn.col<-'lightgray' | |
| myTheme$col$up.col<-'lightgray' | |
| myTheme$col$dn.border <- 'lightgray' | |
| myTheme$col$up.border <- 'lightgray' | |
| # c <- chart_Series( | |
| # x=AGL, | |
| # theme=myTheme, | |
| # name="AGL", | |
| # TA=c("add_SMA(n=nSMA,col=8)") | |
| # ) | |
| # c | |
| # chart.Posn(Portfolio="R2",Symbol=symbol,theme=myTheme, | |
| # TA=c('add_SMA(n=100,col=4, on=1)')) | |
| for(symbol in symbols) | |
| { | |
| if (length(getTxns("macdX", symbol)[,1]) > 1){ | |
| chart.Posn(Portfolio="macdX",Symbol=symbol,theme=myTheme, | |
| TA=c('add_EMA(n=26,col=4, on=1)','add_EMA(n=12,col=2, on=1)'), | |
| prefer='Adjusted') | |
| } | |
| } | |
| Account <- "macdX" | |
| Portfolio <- "macdx" | |
| a <- getAccount(Account) | |
| p <- getPortfolio("macdX") | |
| equity <- a$summary$End.Eq | |
| #p$summary$Long.Value | |
| plot(equity,main="macdX") | |
| charts.PerformanceSummary(ROC(equity)) | |
| ############################################################################### | |
| # R (http://r-project.org/) Quantitative Strategy Model Framework | |
| # | |
| # Copyright (c) 2009-2012 | |
| # Peter Carl, Dirk Eddelbuettel, Brian G. Peterson, Jeffrey Ryan, and Joshua Ulrich | |
| # | |
| # This library is distributed under the terms of the GNU Public License (GPL) | |
| # for full details see the file COPYING | |
| # | |
| # $Id$ | |
| # | |
| ############################################################################## | |
| ##### PLACE THIS BLOCK AT END OF DEMO SCRIPT ################### | |
| book = getOrderBook("macdX") | |
| # stats = tradeStats(port) | |
| # rets = PortfReturns(acct) | |
| ################################################################ | |
| ################### Lets analyse ################### | |
| # assign account and portfolio data to variables "a" and "p" | |
| a <- getAccount("macdX") | |
| p <- getPortfolio("macdX") | |
| names(p$symbols) | |
| # save tradeStats and charts as pdf - for porfolio then for stocks | |
| PDFPath = "C:/Users/jasen/Personal/Personal Work/tradeStats_macd_sig_yahoo.pdf" | |
| pdf(file=PDFPath, onefile=T) | |
| # PORTFOLIO | |
| # tradeStats | |
| #notional <- 0 | |
| longs <- 0 | |
| longwins <- 0 | |
| longloss <- 0 | |
| longpl <- 0 | |
| longnot <- 0 # long notional | |
| longplpct <- 0 | |
| shorts <- 0 | |
| shortwins <- 0 | |
| shortloss <- 0 | |
| shortpl <- 0 | |
| shortnot <- 0 # short notional | |
| shortplpct <- 0 | |
| for(s in symbols){ | |
| if(length(getTxns("macdX", s)[,1]) > 1){ | |
| #txn <- p$symbols[[s]]$txn | |
| netPL <- perTradeStats("macdX", Symbol=s)$Net.Trading.PL | |
| notional <- perTradeStats("macdX", Symbol=s)$Max.Notional.Cost | |
| initpos <- perTradeStats("macdX", Symbol=s)$Init.Pos | |
| longs <- longs + sum(sign(perTradeStats("macdX", Symbol=s)$Init.Pos) > 0) | |
| #long_wins <- length(txn$Net.Txn.Realized.PL[txn$Net.Txn.Realized.PL > 0]) | |
| longwins <- longwins + sum(ifelse(initpos>0 & netPL > 0, TRUE, FALSE)) | |
| #long_loss <- length(txn$Net.Txn.Realized.PL[txn$Net.Txn.Realized.PL < 0]) | |
| longloss <- longloss + sum(ifelse(initpos>0 & netPL < 0, TRUE, FALSE)) | |
| longpl <- longpl + sum(ifelse(initpos>0, netPL, 0)) | |
| longnot <- longnot + sum(ifelse(initpos>0, notional, 0)) | |
| shorts <- shorts + sum(sign(perTradeStats("macdX", Symbol=s)$Init.Pos) < 0) | |
| shortwins <- shortwins + sum(ifelse(initpos<0 & netPL > 0, TRUE, FALSE)) | |
| shortloss <- shortloss + sum(ifelse(initpos<0 & netPL < 0, TRUE, FALSE)) | |
| shortpl <- shortpl + sum(ifelse(initpos<0, netPL, 0)) | |
| shortnot <- shortnot + sum(ifelse(initpos<0, notional, 0)) | |
| print(perTradeStats("macdX", Symbol=s)$Init.Pos) | |
| } | |
| } | |
| longplpct <- paste(format(longpl / longnot * 100, digits = 4), "%", sep = "") | |
| shortplpct <- paste(format(shortpl / abs(shortnot) * 100, digits = 4), "%", sep = "") | |
| #trades <- sum(tradeStats("macdX")[,"Num.Trades"]) | |
| #numwin <- sum(tradeStats("macdX")[,"Percent.Positive"] * tradeStats("macdX")[,"Num.Trades"]) / 100 | |
| wins <- longwins + shortwins | |
| #numloss <- sum(tradeStats("macdX")[,"Percent.Negative"] * tradeStats("macdX")[,"Num.Trades"]) / 100 | |
| losses <- longloss + shortloss | |
| trades <- wins + losses | |
| #pnl <- tail(a$summary$End.Eq, 1) - initEq | |
| pnl <- format(sum(p$summary$Net.Trading.PL), digits = 0, big.mark = " ", scientific=FALSE) | |
| pnlpct <- paste(format(sum(p$summary$Net.Trading.PL) / initEq * 100, digits = 4), "%", sep = "") | |
| summary_headings <- c("Trades", "Wins", "Losses", "PnL", "%PnL") | |
| longpl <- format(round(longpl, 0), big.mark = " ", scientific=FALSE) | |
| long_stats <- data.frame(cbind(longs, longwins, longloss, longpl, longplpct)) | |
| names(long_stats) <- summary_headings | |
| shortpl <- format(round(shortpl, 0), big.mark = " ", scientific=FALSE) | |
| short_stats <- data.frame(cbind(shorts, shortwins, shortloss, shortpl, shortplpct)) | |
| names(short_stats) <- summary_headings | |
| port_stats <- data.frame(cbind(trades, wins, losses, pnl, pnlpct)) | |
| names(port_stats) <- summary_headings | |
| df <- as.data.frame(cbind(t(long_stats), t(short_stats), t(port_stats))) | |
| names(df) <- c("LONGS", "SHORTS", "TOTAL") | |
| textplot(df) | |
| # chart | |
| e <- ROC(equity)[-(1:700)] | |
| colnames(e) <- Account | |
| # bench_equity <- xts(indx$PX_LAST, indx$date) | |
| # bench <- ROC(bench_equity)[-(1:700)] | |
| # colnames(bench) <- benchmark | |
| # charts.PerformanceSummary(merge(e,bench)) | |
| charts.PerformanceSummary(e) | |
| getSymbols('^GSPC', src='yahoo', index.class=c("POSIXt","POSIXct"),from='1998-02-01') | |
| SNP <- ROC(Cl(GSPC))[-(1:700)] | |
| charts.PerformanceSummary(merge(e,SNP)) | |
| # equity <- a$summary$End.Eq[-(1:700)] | |
| # plot(equity,main="macdX Equity Curve") | |
| #textplot(cbind(table.AnnualizedReturns(e), table.AnnualizedReturns(bench))) | |
| textplot(table.AnnualizedReturns(e)) | |
| monthly_equity <- to.monthly(equity[-(1:700)], OHLC = FALSE) | |
| mon_ret <- ROC(monthly_equity) | |
| textplot(t(table.CalendarReturns(mon_ret))) | |
| title(main = Account) | |
| # monthly_bench <- to.monthly(bench_equity[-(1:700)], OHLC = FALSE) | |
| # bench_ret <- ROC(monthly_bench) | |
| # colnames(bench_ret) <- benchmark | |
| # textplot(t(table.CalendarReturns(bench_ret))) | |
| # title(main = benchmark) | |
| chart.Bar(p$summary$Long.Value) | |
| #mcsim("macdX", "macdX", n=1000, l=1, gap = 700) | |
| # tradestats ("Additional Stats" equivalent) | |
| # STOCKS | |
| # how many stocks per pdf page? | |
| par(mfrow=c(2,1)) | |
| k <- 8 | |
| if(length(symbols) > k){ | |
| for (i in 1:ceiling(length(symbols)/k)){ | |
| textplot(t(tradeStats("macdX", symbols[(i*k-(k-1)):(i*k)]))) | |
| #title("tradeStats") | |
| } | |
| } else { | |
| textplot(t(tradeStats("macdX", symbols[]))) | |
| #title("tradeStats") | |
| } | |
| par(mfrow=c(1,1)) | |
| for(symbol in symbols) | |
| { | |
| if (length(getTxns("macdX", symbol)[,1]) > 1){ | |
| chart.Posn(Portfolio="macdX",Symbol=symbol,theme=myTheme, | |
| TA=c('add_SMA(n=200,col=4, on=1)')) | |
| } | |
| } | |
| par(mfrow=c(1,1)) | |
| #textplot(t(tradeStats("macdX"))) | |
| dev.off() | |
| t2 <- Sys.time() | |
| difftime(t2,t1) | |
| t1 <- Sys.time() | |
| macdX.wr.equity.mcsim <- mcsim("macdX", n=10, replacement = TRUE, use = "equity", gap = 700, l = 10) | |
| macdX.wr.txns.mcsim <- mcsim("macdX", n=10, replacement = TRUE, use = "txns", l = 1) | |
| t2 <- Sys.time() | |
| difftime(t2,t1) | |
| plot(macdX.wr.mcsim) | |
| blog.seed <- macdX.wr.mcsim$seed | |
| set.seed(blog.seed) | |
| t1 <- Sys.time() | |
| macdX.nr.mcsim <- mcsim("macdX", n=1000, replacement = FALSE, gap = 700, l = 10) | |
| t2 <- Sys.time() | |
| difftime(t2,t1) | |
| plot(macdX.nr.mcsim) | |
| t1 <- Sys.time() | |
| macdX.wr.txnsim <- txnsim("macdX", n=1000, replacement = TRUE, tradeDef = "flat.to.flat") | |
| t2 <- Sys.time() | |
| difftime(t2,t1) | |
| plot(macdX.wr.txnsim) | |
| t1 <- Sys.time() | |
| macdX.nr.txnsim <- txnsim("macdX", n=1000, replacement = FALSE, tradeDef = "flat.to.flat") | |
| t2 <- Sys.time() | |
| difftime(t2,t1) | |
| plot(macdX.nr.txnsim) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment