Serhat Akay
Serhat Akay

Reputation: 125

Quantstrat Multiple Symbol Strategy - Trades with chronological order rather than alphabetically when investing with full equity

A minimum reproducible example:

library(quantstrat)

  startd<-"2022-08-01 01:00:00"
  finishd<-"2022-08-01 02:15:00"
  symbols<-c("AXSUSD", "XRPUSD")
  
 AXSUSD<- structure(c(18.59, 18.59, 18.56, 18.51, 18.53, 18.5, 18.5, 18.5, 
              18.5, 18.47, 18.49, 18.48, 18.46, 18.45, 18.43, 18.41, 18.43, 
              18.4, 18.41, 18.42, 18.4, 18.4, 18.35, 18.4, 18.37, 18.35, 18.34, 
              18.28, 18.26, 18.26, 18.29, 18.26, 18.26, 18.25, 18.25, 18.24, 
              18.25, 18.23, 18.2, 18.15, 18.06, 18.07, 18.07, 18.06, 18.06, 
              18.09, 18.05, 18.03, 18.01, 18.02, 18.01, 18.03, 18.09, 18.05, 
              18.06, 18.05, 18.02, 18.06, 18.07, 18.1, 18.15, 18.11, 18.09, 
              18.06, 18.08, 18.08, 18.03, 18.04, 18.03, 18.02, 18.02, 18, 18.01, 
              18.05, 18.03, 18.05, 18.6, 18.59, 18.56, 18.53, 18.55, 18.51, 
              18.51, 18.51, 18.5, 18.49, 18.51, 18.48, 18.47, 18.45, 18.43, 
              18.44, 18.43, 18.41, 18.43, 18.43, 18.41, 18.4, 18.4, 18.4, 18.39, 
              18.36, 18.36, 18.28, 18.27, 18.31, 18.29, 18.27, 18.27, 18.28, 
              18.27, 18.25, 18.25, 18.24, 18.21, 18.15, 18.1, 18.1, 18.09, 
              18.07, 18.11, 18.1, 18.06, 18.04, 18.04, 18.02, 18.03, 18.08, 
              18.09, 18.06, 18.06, 18.06, 18.06, 18.08, 18.1, 18.15, 18.15, 
              18.11, 18.09, 18.08, 18.09, 18.08, 18.06, 18.06, 18.03, 18.02, 
              18.02, 18.03, 18.04, 18.06, 18.05, 18.06, 18.57, 18.56, 18.5, 
              18.48, 18.51, 18.49, 18.48, 18.5, 18.47, 18.47, 18.48, 18.46, 
              18.44, 18.42, 18.4, 18.4, 18.4, 18.39, 18.41, 18.39, 18.39, 18.34, 
              18.35, 18.36, 18.33, 18.34, 18.27, 18.24, 18.25, 18.25, 18.26, 
              18.24, 18.24, 18.24, 18.24, 18.24, 18.24, 18.19, 18.16, 18.03, 
              18.06, 18.04, 18.04, 18.03, 18.05, 18.05, 18.04, 18.01, 18.01, 
              18, 17.98, 18.02, 18.05, 18.03, 18.05, 18.01, 18.01, 18.06, 18.05, 
              18.1, 18.11, 18.07, 18.07, 18.06, 18.07, 18.01, 18.02, 18.04, 
              18, 18.01, 17.99, 18, 18, 18.02, 18.03, 18.04, 18.59, 18.56, 
              18.51, 18.53, 18.51, 18.5, 18.49, 18.51, 18.47, 18.48, 18.49, 
              18.47, 18.44, 18.43, 18.41, 18.43, 18.4, 18.41, 18.41, 18.39, 
              18.39, 18.35, 18.39, 18.37, 18.35, 18.34, 18.28, 18.25, 18.25, 
              18.29, 18.27, 18.26, 18.25, 18.25, 18.24, 18.24, 18.24, 18.2, 
              18.16, 18.07, 18.07, 18.08, 18.07, 18.07, 18.09, 18.05, 18.04, 
              18.03, 18.02, 18, 18.01, 18.08, 18.05, 18.06, 18.06, 18.01, 18.06, 
              18.08, 18.1, 18.15, 18.11, 18.1, 18.07, 18.08, 18.08, 18.02, 
              18.04, 18.04, 18.02, 18.02, 18, 18.01, 18.04, 18.04, 18.05, 18.06, 
              267.01, 541.51, 1476.94, 824.6, 291.32, 423.93, 256.52, 119.27, 
              295.6, 572.75, 502.21, 225.61, 430.23, 710.36, 763.7, 392.99, 
              190.62, 790.51, 453.41, 254.25, 643.42, 2042.63, 465.7, 649.73, 
              1482.22, 245.25, 1525.01, 3044.69, 1639.7, 1094.5, 407.23, 1863.08, 
              1270.13, 1476.93, 1429.3, 3169.91, 2142.71, 2210.54, 1308.62, 
              3227.14, 805.05, 1446.61, 570.95, 995.8, 517.49, 559.74, 187.41, 
              873.55, 296.18, 2185.88, 1489.49, 753.01, 492.74, 185.89, 296.91, 
              1312.9, 338, 673.39, 938.74, 514.05, 237.6, 412.84, 189.4, 448.67, 
              370.31, 472.12, 1775.97, 119.69, 250.69, 173.07, 1091.01, 505.81, 
              244.32, 340.67, 142, 151.03), class = c("xts", "zoo"), index = structure(c(1659304800, 
                                                                                         1659304860, 1659304920, 1659304980, 1659305040, 1659305100, 1659305160, 
                                                                                         1659305220, 1659305280, 1659305340, 1659305400, 1659305460, 1659305520, 
                                                                                         1659305580, 1659305640, 1659305700, 1659305760, 1659305820, 1659305880, 
                                                                                         1659305940, 1659306000, 1659306060, 1659306120, 1659306180, 1659306240, 
                                                                                         1659306300, 1659306360, 1659306420, 1659306480, 1659306540, 1659306600, 
                                                                                         1659306660, 1659306720, 1659306780, 1659306840, 1659306900, 1659306960, 
                                                                                         1659307020, 1659307080, 1659307140, 1659307200, 1659307260, 1659307320, 
                                                                                         1659307380, 1659307440, 1659307500, 1659307560, 1659307620, 1659307680, 
                                                                                         1659307740, 1659307800, 1659307860, 1659307920, 1659307980, 1659308040, 
                                                                                         1659308100, 1659308160, 1659308220, 1659308280, 1659308340, 1659308400, 
                                                                                         1659308460, 1659308520, 1659308580, 1659308640, 1659308700, 1659308760, 
                                                                                         1659308820, 1659308880, 1659308940, 1659309000, 1659309060, 1659309120, 
                                                                                         1659309180, 1659309240, 1659309300), tzone = "", tclass = c("POSIXct", 
                                                                                                                                                     "POSIXt")), .Dim = c(76L, 5L), .Dimnames = list(NULL, c("Open", 
                                                                                                                                                                                                             "High", "Low", "Close", "Volume")))
  
 
 
 XRPUSD<-structure(c(0.3872, 0.3872, 0.3869, 0.3863, 0.387, 0.3869, 0.3869, 
                     0.3867, 0.3867, 0.3864, 0.3865, 0.3864, 0.3863, 0.386, 0.3859, 
                     0.3858, 0.3866, 0.3863, 0.3864, 0.3866, 0.3869, 0.3865, 0.3858, 
                     0.3867, 0.3865, 0.3858, 0.3857, 0.3848, 0.3848, 0.3852, 0.3853, 
                     0.3853, 0.3843, 0.3838, 0.3836, 0.3832, 0.383, 0.383, 0.3829, 
                     0.3819, 0.382, 0.382, 0.3829, 0.3822, 0.3822, 0.3825, 0.3823, 
                     0.382, 0.3816, 0.3818, 0.3812, 0.3814, 0.3823, 0.3816, 0.3815, 
                     0.3816, 0.3812, 0.3816, 0.3817, 0.3817, 0.3822, 0.3818, 0.381, 
                     0.3813, 0.3818, 0.3813, 0.381, 0.3812, 0.3812, 0.3805, 0.38, 
                     0.3787, 0.3791, 0.3802, 0.3802, 0.38, 0.3874, 0.3872, 0.3869, 
                     0.387, 0.3873, 0.387, 0.3869, 0.3869, 0.3867, 0.3865, 0.3868, 
                     0.3864, 0.3863, 0.3863, 0.3863, 0.3868, 0.3867, 0.3864, 0.3867, 
                     0.3871, 0.3869, 0.3865, 0.3868, 0.3867, 0.3865, 0.3859, 0.3858, 
                     0.385, 0.3855, 0.3856, 0.3853, 0.3854, 0.3845, 0.3843, 0.3838, 
                     0.3833, 0.3833, 0.3832, 0.383, 0.3823, 0.3821, 0.3833, 0.383, 
                     0.3825, 0.383, 0.3827, 0.3824, 0.3821, 0.3818, 0.3818, 0.3819, 
                     0.3823, 0.3824, 0.3816, 0.3816, 0.3816, 0.3817, 0.3819, 0.3824, 
                     0.3823, 0.3823, 0.3818, 0.3815, 0.3818, 0.3818, 0.3814, 0.3813, 
                     0.3813, 0.3812, 0.3805, 0.3801, 0.3795, 0.3802, 0.3806, 0.3803, 
                     0.3803, 0.3871, 0.3869, 0.3861, 0.3859, 0.3867, 0.3867, 0.3866, 
                     0.3867, 0.3863, 0.3862, 0.3863, 0.386, 0.3859, 0.3859, 0.3858, 
                     0.3857, 0.3861, 0.3858, 0.3864, 0.3865, 0.3865, 0.3857, 0.3858, 
                     0.3865, 0.3858, 0.3856, 0.3847, 0.3843, 0.3847, 0.3847, 0.385, 
                     0.3841, 0.3837, 0.3836, 0.3831, 0.383, 0.383, 0.3829, 0.3818, 
                     0.3812, 0.3816, 0.3819, 0.3819, 0.3818, 0.3822, 0.3823, 0.3819, 
                     0.3816, 0.3813, 0.3812, 0.38, 0.3814, 0.3813, 0.3809, 0.3813, 
                     0.381, 0.3812, 0.3816, 0.3814, 0.3816, 0.3817, 0.3809, 0.3809, 
                     0.3811, 0.3813, 0.3806, 0.3809, 0.3812, 0.3804, 0.3793, 0.3782, 
                     0.3786, 0.3791, 0.3798, 0.3801, 0.38, 0.3872, 0.387, 0.3863, 
                     0.387, 0.3869, 0.387, 0.3868, 0.3868, 0.3864, 0.3864, 0.3863, 
                     0.3862, 0.386, 0.386, 0.3858, 0.3866, 0.3863, 0.3864, 0.3866, 
                     0.3869, 0.3865, 0.3858, 0.3867, 0.3866, 0.3859, 0.3856, 0.3849, 
                     0.3847, 0.3852, 0.3854, 0.3853, 0.3843, 0.3838, 0.3836, 0.3833, 
                     0.3831, 0.383, 0.383, 0.3819, 0.3819, 0.382, 0.3829, 0.3821, 
                     0.3824, 0.3825, 0.3823, 0.382, 0.3816, 0.3818, 0.3812, 0.3815, 
                     0.3823, 0.3816, 0.3814, 0.3815, 0.3812, 0.3816, 0.3817, 0.3817, 
                     0.3823, 0.3817, 0.381, 0.3814, 0.3818, 0.3813, 0.3809, 0.3812, 
                     0.3812, 0.3804, 0.38, 0.3787, 0.3791, 0.3802, 0.3802, 0.3802, 
                     0.3801, 173535, 116599, 218382, 246121, 128348, 99462, 22511, 
                     64515, 97513, 55926, 189760, 73759, 175517, 101904, 265970, 87041, 
                     61687, 176343, 86575, 180590, 58751, 224686, 150028, 111829, 
                     156258, 46998, 535117, 460168, 337710, 142897, 118871, 280809, 
                     156589, 166904, 355699, 175117, 194193, 139842, 372572, 672156, 
                     157021, 241500, 219450, 159943, 152822, 103950, 65322, 67241, 
                     123305, 120647, 1444688, 171372, 209580, 248285, 83473, 90654, 
                     122571, 114348, 239920, 72403, 134801, 967515, 662778, 110607, 
                     170073, 124642, 50443, 36772, 82321, 641158, 739741, 155703, 
                     46420, 147300, 36951, 26022), class = c("xts", "zoo"), index = structure(c(1659304800, 
                                                                                                1659304860, 1659304920, 1659304980, 1659305040, 1659305100, 1659305160, 
                                                                                                1659305220, 1659305280, 1659305340, 1659305400, 1659305460, 1659305520, 
                                                                                                1659305580, 1659305640, 1659305700, 1659305760, 1659305820, 1659305880, 
                                                                                                1659305940, 1659306000, 1659306060, 1659306120, 1659306180, 1659306240, 
                                                                                                1659306300, 1659306360, 1659306420, 1659306480, 1659306540, 1659306600, 
                                                                                                1659306660, 1659306720, 1659306780, 1659306840, 1659306900, 1659306960, 
                                                                                                1659307020, 1659307080, 1659307140, 1659307200, 1659307260, 1659307320, 
                                                                                                1659307380, 1659307440, 1659307500, 1659307560, 1659307620, 1659307680, 
                                                                                                1659307740, 1659307800, 1659307860, 1659307920, 1659307980, 1659308040, 
                                                                                                1659308100, 1659308160, 1659308220, 1659308280, 1659308340, 1659308400, 
                                                                                                1659308460, 1659308520, 1659308580, 1659308640, 1659308700, 1659308760, 
                                                                                                1659308820, 1659308880, 1659308940, 1659309000, 1659309060, 1659309120, 
                                                                                                1659309180, 1659309240, 1659309300), tzone = "", tclass = c("POSIXct", 
                                                                                                                                                            "POSIXt")), .Dim = c(76L, 5L), .Dimnames = list(NULL, c("Open", 
                                                                                                                                                                                                                    "High", "Low", "Close", "Volume")))
 
  symbols <- setNames(symbols, symbols)

  osInvestFull <- function (data, timestamp, orderqty, ordertype, 
                           orderside, equity, portfolio, symbol, ruletype, ..., initEq) {
    datePos <- format(timestamp+60, "%Y-%m-%d %H:%M:%S")
    
    
    updatePortf(Portfolio=portfolio,Symbol=symbol,Dates=paste0(start(data), 
                                                               "/", datePos))
    # After updating portfolio profit, we can extract the Net.Trading.PL earned up to datePos.
    trading_pl <- sum(.getPortfolio(portfolio)$summary$Net.Trading.PL)

  equity <- initEq + trading_pl
  print(paste("Equity", equity, sep="="))
  ClosePrice <- getPrice(data, prefer = "Close")[datePos]
  
  if (orderside=="short") {
  UnitSize <- as.numeric((-1*equity / ClosePrice))
  }
  
  else {
    UnitSize <- as.numeric((equity / ClosePrice))
  }
  
  UnitSize
  }
  
  # Set the timezone to UTC
  Sys.setenv(TZ="Europe/Istanbul")
  
  rm.strat(portfolio.st)
  rm.strat(strategy.st)
  rm.strat(account.st)
  
  stock.str = symbols
  
  # Set the currency to USD
  currency("USD")
  
  #getSymbols(stock.str,from=startDate, to= Sys.Date())
  
  for(symbol in symbols){
    stock(symbols, currency="USD",multiplier=1)
  }
  
  
  # Create initdate, from, and to strings
  initdate <- "2022-08-01 00:59:00"
  startDate <- "2022-08-01 01:00:00"
  to <- "2022-08-01 02:15:00"
  
  
  # Define your trade size and initial equity
  
  initEq <- 1000
  
  strategy.st <- "X_STRAT"
  portfolio.st <- "X_PORTF"
  account.st <- "X_ACCT"
  
  # Initialize the portfolio
  initPortf(portfolio.st, symbols = symbols, initDate =initdate , currency = "USD")
  
  # Initialize the account
  initAcct(account.st, portfolios = portfolio.st, initDate = initdate, currency = "USD", initEq = initEq)
  
  # Initialize the orders
  initOrders(portfolio.st, initDate = initdate)
  
  # Store the strategy
  strategy(strategy.st, store = TRUE)
  
  fee <- function(TxnQty, TxnPrice, Symbol) {
    
    
    return(0 * abs(TxnQty * TxnPrice))
  }
  
  add.indicator(strategy = strategy.st, name = "SMA",
                arguments = list(x = quote(Cl(mktdata)), n=10),
                label ="nFast")
  
  
  add.indicator(strategy = strategy.st, name = "SMA",
                arguments = list(x = quote(Cl(mktdata)), n=20),
                label = "nSlow")
  
  add.signal(strategy = strategy.st, 
             name= "sigCrossover",
             arguments =  list(columns = c("nFast", "nSlow"),
                               relationship = "gte"),
             label = "longenter")
  
  add.signal(strategy = strategy.st,
             name= "sigCrossover", 
             arguments =  list(columns = c("nFast",
                                           "nSlow"), 
                               relationship = "lt"),
             label = "longexit")
  
  #Add rules for entering positions
  #enter long position
  add.rule(strategy.st, 
           name = "ruleSignal", 
           arguments = list(sigcol = "longenter",
                            sigval = TRUE,
                            osFUN= osInvestFull,
                            ordertype = "market",
                            orderside = "long",
                            orderset= "ocolong",
                            prefer = "Close",
                            TxnFees = 0,
                            replace = FALSE),
           type = "enter",
           label = "EnterLong")
  
  
  
  #exit long
  add.rule(strategy = strategy.st, 
           name = "ruleSignal",
           arguments = list(sigcol = "longexit",
                            sigval = TRUE,
                            TxnFees=0,
                            replace = FALSE, 
                            orderside = "long", 
                            ordertype = "market",
                            orderqty = "all", 
                            tmult = TRUE,
                            prefer = "Close",
                            orderset="ocolong"), 
           type = "exit", 
           path.dep=TRUE, 
           label = "ExitLong", 
           enabled=TRUE)
  
  
  add.rule(strategy = strategy.st, name ='rulePctEquity', arguments=list(rebalance_on='days',
                                                                         trade.percent=1/length(symbols), refprice=quote(last(getPrice(mktdata)[paste('::',as.character(curIndex),sep='')][,1])),digits=0),
           type='rebalance',label='rebalance')
  
  # Must add maxpos:
  #for(symbol in symbols){ addPosLimit(portfolio.st, symbol, timestamp = startDate, maxpos = 100000000, minpos=-1000000000) }

  applyStrategy(strategy=strategy.st, portfolios=portfolio.st, initEq = initEq, prefer="Close")


#[1] "Equity=1000"
#[1] "2022-08-01 02:00:00 AXSUSD 55.2181115405853 @ 18.11"
#[1] "2022-08-01 02:10:00 AXSUSD -55.2181115405853 @ 18"
#[1] "Equity=1000"
#[1] "2022-08-01 01:25:00 XRPUSD 2593.36099585062 @ 0.3856"
#[1] "2022-08-01 01:26:00 XRPUSD -2593.36099585062 @ 0.3849"

XRP trade is before the AXS trade chronologically as shown above. XRP trade's PL plus initial equity is supposed to be the total amount of AXS trade since I wrote a function to invest full equity. At 01:59 my equity should 1000*(1+(.3849/.3856-1))=$998.1846 since it is a loss trade and no transaction fees.

But when you look at AXS enter order amount it is still $1000 due to the fact that quantstrat first enters AXS order (enters the order alphabetically with respect to symbol vector)

How can I fix this situation to sort the orders chronologically and enter the AXS order after XRP order with $998.1846 equity?

Thanks in advance

Upvotes: 1

Views: 70

Answers (0)

Related Questions