[Blotter-commits] r1736 - in pkg/quantstrat: R inst/tests tests

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Fri Mar 25 21:40:30 CET 2016


Author: bodanker
Date: 2016-03-25 21:40:30 +0100 (Fri, 25 Mar 2016)
New Revision: 1736

Added:
   pkg/quantstrat/inst/tests/test_osMaxPos.R
Modified:
   pkg/quantstrat/R/osFUNs.R
   pkg/quantstrat/tests/run-all.R
Log:
Address issues w/osMaxPos and add tests (#6306)

R-Forge issue #6306 highlights two potential issues with osMasPos. I
cannot seem to trigger any bug via tests for the first problem:
  if(orderqty+pos > PosLimit[,"MaxPos"])
      orderqty <- PosLimit[,"MinPos"]-pos
which seems like it should be:
  if(orderqty-pos < PosLimit[,"MinPos"])
      orderqty <- PosLimit[,"MinPos"]+pos

The second error is most certainly a problem:
  orderqty <- pos #flatten position, don't cross through zero
should be
  orderqty <- -pos #flatten position, don't cross through zero
because we are buying to cover a short position.

Move the ruletype == "risk" and orderqty == "all" checks to the
beginning of the function, so we can throw an error for unsupported
combinations.

Replace "&" with "&&" inside if statements, so we get the benefit
of short-circuiting when the first isn't TRUE. This helps handle
orderside = NULL more gracefully.

Use as.integer(orderqty) to strip attributes (e.g. dim, xts stuff, etc)
that come from the position limit object when we are at position limits.

Add unit tests!


Modified: pkg/quantstrat/R/osFUNs.R
===================================================================
--- pkg/quantstrat/R/osFUNs.R	2016-03-25 17:55:39 UTC (rev 1735)
+++ pkg/quantstrat/R/osFUNs.R	2016-03-25 20:40:30 UTC (rev 1736)
@@ -145,9 +145,16 @@
         stop(paste('no position limit defined for portfolio', portfolio))
 	
 	#TODO add handling for orderqty='all', and handle risk ruletype separately
+    if(is.character(orderqty)) {
+        if(ruletype == "risk" && orderqty == "all") {
+            orderqty <- pos * -1
+        } else {
+            stop("orderqty ", orderqty, " is not supported for non-risk ruletypes")
+        }
+    }
 	
 	#check order side
-	if(is.null(orderside) & !isTRUE(orderqty == 0)){
+	if(is.null(orderside) && !isTRUE(orderqty == 0)) {
 		curqty<-pos
 		if (curqty>0 ){
 			#we have a long position
@@ -166,7 +173,7 @@
 	
 	# check levels
 	# buy long
-    if(orderqty>0 & orderside=='long'){
+    if(orderqty>0 && orderside=='long') {
         if ((orderqty+pos)<PosLimit[,"MaxPos"]) {
             #we have room to expand the position
             if(orderqty<=(PosLimit[,"MaxPos"]/PosLimit[,"LongLevels"]) ) {
@@ -179,14 +186,13 @@
             orderqty<-ifelse((PosLimit[,"MaxPos"]-pos)<=round(PosLimit[,"MaxPos"]/PosLimit[,"LongLevels"],0),PosLimit[,"MaxPos"]-pos, round(PosLimit[,"MaxPos"]/PosLimit[,"LongLevels"],0)) 
             if(orderqty+pos>PosLimit[,"MaxPos"]) orderqty <- PosLimit[,"MaxPos"]-pos
         }
-        return(orderqty)
+        return(as.integer(orderqty))
     }
     
     #sell long
-    if(orderqty<0 & orderside=='long'){
+    if(orderqty<0 && orderside=='long') {
 		if(ruletype=='risk'){
-          if(orderqty=='all') return(-1*pos)
-          else return(orderqty)
+          return(orderqty)
         } 
 		if ((orderqty+pos)>=0) {
             return(orderqty)
@@ -198,7 +204,7 @@
     }
     
     #sell short
-    if(orderqty<0 & orderside=='short'){
+    if(orderqty<0 && orderside=='short') {
         if ((orderqty+pos)>PosLimit[,"MinPos"]) {
             #we have room to expand the position
             if(orderqty>=(PosLimit[,"MinPos"]/PosLimit[,"ShortLevels"]) ) {
@@ -211,19 +217,18 @@
             orderqty<-ifelse((PosLimit[,"MinPos"]-pos)>=round(PosLimit[,"MinPos"]/PosLimit[,"ShortLevels"],0),PosLimit[,"MinPos"]-pos, round(PosLimit[,"MinPos"]/PosLimit[,"ShortLevels"],0)) 
             if(orderqty+pos>PosLimit[,"MaxPos"]) orderqty <- PosLimit[,"MinPos"]-pos
         }
-        return(orderqty)
+        return(as.integer(orderqty))
     }
     
     #buy cover short
-    if(orderqty>0 & orderside=='short'){
+    if(orderqty>0 && orderside=='short') {
         if(ruletype=='risk'){
-            if(orderqty=='all') return(-1*pos)
-            else return(orderqty)
+            return(orderqty)
         } 
         if ((orderqty+pos)<=0) {
             return(orderqty)
         } else {
-            orderqty<-pos #flatten position, don't cross through zero
+            orderqty <- -pos #flatten position, don't cross through zero
             #TODO add code to break into two orders?
             return(orderqty)
         }

Added: pkg/quantstrat/inst/tests/test_osMaxPos.R
===================================================================
--- pkg/quantstrat/inst/tests/test_osMaxPos.R	                        (rev 0)
+++ pkg/quantstrat/inst/tests/test_osMaxPos.R	2016-03-25 20:40:30 UTC (rev 1736)
@@ -0,0 +1,167 @@
+stopifnot(require(testthat))
+stopifnot(require(quantstrat))
+context("osMaxPos")
+
+# setup
+symbol <- "test"
+portfolio <- "test_osMaxPos"
+initPortf(portfolio, symbol, -3000)
+
+addPosLimit(portfolio, symbol, "2013-09-01", 8000, 8, -4000, 4)
+timestamp <- as.Date("2013-09-09")
+
+###############################################################################
+# short position, ruletype == "risk"
+test_that("risk-flatten short w/orderqty = 'all'", {
+  qty <- osMaxPos(NULL, timestamp, "all", "", "short", portfolio, symbol, "risk")
+  expect_equal(qty, 3000)
+  qty <- osMaxPos(NULL, timestamp, "all", "", NULL, portfolio, symbol, "risk")
+  expect_equal(qty, 3000)
+})
+
+# FIXME: Should risk be able to take position across zero?
+test_that("risk-flatten short w/orderqty > abs(position)", {
+  qty <- osMaxPos(NULL, timestamp, 4000, "", "short", portfolio, symbol, "risk")
+  expect_equal(qty, 4000)
+  qty <- osMaxPos(NULL, timestamp, 4000, "", NULL, portfolio, symbol, "risk")
+  expect_equal(qty, 4000)
+})
+
+test_that("risk-reduce short", {
+  qty <- osMaxPos(NULL, timestamp, 2000, "", "short", portfolio, symbol, "risk")
+  expect_equal(qty, 2000)
+  qty <- osMaxPos(NULL, timestamp, 2000, "", NULL, portfolio, symbol, "risk")
+  expect_equal(qty, 2000)
+})
+
+# FIXME: What should these do? Risk rules probably shouldn't be able to increase position
+#test_that("risk-increase short within limits", {
+#  qty <- osMaxPos(NULL, timestamp, -1000, "", "short", portfolio, symbol, "risk")
+#  qty <- osMaxPos(NULL, timestamp, -1000, "", NULL, portfolio, symbol, "risk")
+#})
+#
+#test_that("risk-increase short beyond limits", {
+#  qty <- osMaxPos(NULL, timestamp, -2000, "", "short", portfolio, symbol, "risk")
+#  qty <- osMaxPos(NULL, timestamp, -2000, "", NULL, portfolio, symbol, "risk")
+#})
+
+###############################################################################
+# short position, ruletype != "risk"
+test_that("flatten short w/orderqty = 'all'", {
+  # ordertype="all" is not currently supported for non-risk ruletypes
+  expect_error(osMaxPos(NULL, timestamp, "all", "", "short", portfolio, symbol, ""))
+})
+
+test_that("flatten short w/orderqty > abs(position)", {
+  qty <- osMaxPos(NULL, timestamp, 4000, "", "short", portfolio, symbol, "")
+  expect_equal(qty, 3000)
+  qty <- osMaxPos(NULL, timestamp, 4000, "", NULL, portfolio, symbol, "")
+  expect_equal(qty, 3000)
+})
+
+test_that("reduce short", {
+  qty <- osMaxPos(NULL, timestamp, 2000, "", "short", portfolio, symbol, "")
+  expect_equal(qty, 2000)
+  qty <- osMaxPos(NULL, timestamp, 2000, "", NULL, portfolio, symbol, "")
+  expect_equal(qty, 2000)
+})
+
+test_that("increase short within limits", {
+  qty <- osMaxPos(NULL, timestamp, -1000, "", "short", portfolio, symbol, "risk")
+  expect_equal(qty, -1000)
+  qty <- osMaxPos(NULL, timestamp, -1000, "", NULL, portfolio, symbol, "risk")
+  expect_equal(qty, -1000)
+})
+
+test_that("increase short beyond limits", {
+  qty <- osMaxPos(NULL, timestamp, -2000, "", "short", portfolio, symbol, "risk")
+  expect_equal(qty, -1000)
+  qty <- osMaxPos(NULL, timestamp, -2000, "", NULL, portfolio, symbol, "risk")
+  expect_equal(qty, -1000)
+})
+
+# add transaction to make portfolio long
+suppressWarnings(addTxn(portfolio, symbol, timestamp-1L, 10000, 1, verbose=FALSE))
+
+###############################################################################
+# long position, ruletype == "risk"
+test_that("risk-flatten long w/orderqty = 'all'", {
+  qty <- osMaxPos(NULL, timestamp, "all", "", "long", portfolio, symbol, "risk")
+  expect_equal(qty, -7000)
+  qty <- osMaxPos(NULL, timestamp, "all", "", NULL, portfolio, symbol, "risk")
+  expect_equal(qty, -7000)
+})
+
+test_that("risk-reduce long", {
+  qty <- osMaxPos(NULL, timestamp, -2000, "", "long", portfolio, symbol, "risk")
+  expect_equal(qty, -2000)
+  qty <- osMaxPos(NULL, timestamp, -2000, "", NULL, portfolio, symbol, "risk")
+  expect_equal(qty, -2000)
+})
+
+# FIXME: Should risk be able to take position across zero?
+test_that("risk-flatten long w/orderqty > abs(position)", {
+  qty <- osMaxPos(NULL, timestamp, -8000, "", "long", portfolio, symbol, "risk")
+  expect_equal(qty, -8000)
+  qty <- osMaxPos(NULL, timestamp, -8000, "", NULL, portfolio, symbol, "risk")
+  expect_equal(qty, -8000)
+})
+
+# FIXME: What should these do? Risk rules probably shouldn't be able to increase position
+#test_that("risk-increase long within limits", {
+#  qty <- osMaxPos(NULL, timestamp, 1000, "", "long", portfolio, symbol, "risk")
+#  qty <- osMaxPos(NULL, timestamp, 1000, "", NULL, portfolio, symbol, "risk")
+#})
+#
+#test_that("risk-increase long beyond limits", {
+#  qty <- osMaxPos(NULL, timestamp, 2000, "", "long", portfolio, symbol, "risk")
+#  qty <- osMaxPos(NULL, timestamp, 2000, "", NULL, portfolio, symbol, "risk")
+#})
+
+###############################################################################
+# long position, ruletype != "risk"
+test_that("flatten long w/orderqty = 'all'", {
+  # ordertype="all" is not currently supported for non-risk ruletypes
+  expect_error(osMaxPos(NULL, timestamp, "all", "", "short", portfolio, symbol, ""))
+})
+
+test_that("reduce long", {
+  qty <- osMaxPos(NULL, timestamp, -2000, "", "long", portfolio, symbol, "")
+  expect_equal(qty, -2000)
+  qty <- osMaxPos(NULL, timestamp, -2000, "", NULL, portfolio, symbol, "")
+  expect_equal(qty, -2000)
+})
+
+test_that("flatten long w/orderqty > abs(position)", {
+  qty <- osMaxPos(NULL, timestamp, -8000, "", "long", portfolio, symbol, "")
+  expect_equal(qty, -7000)
+  qty <- osMaxPos(NULL, timestamp, -8000, "", NULL, portfolio, symbol, "")
+  expect_equal(qty, -7000)
+})
+
+test_that("increase long within limits", {
+  qty <- osMaxPos(NULL, timestamp, 1000, "", "long", portfolio, symbol, "risk")
+  expect_equal(qty, 1000)
+  qty <- osMaxPos(NULL, timestamp, 1000, "", NULL, portfolio, symbol, "risk")
+  expect_equal(qty, 1000)
+})
+
+test_that("increase long beyond limits", {
+  qty <- osMaxPos(NULL, timestamp, 2000, "", "long", portfolio, symbol, "risk")
+  expect_equal(qty, 1000)
+  qty <- osMaxPos(NULL, timestamp, 2000, "", NULL, portfolio, symbol, "risk")
+  expect_equal(qty, 1000)
+})
+
+###############################################################################
+test_that("zero order quantity", {
+  qty <- osMaxPos(NULL, timestamp, 0, "", "long", portfolio, symbol, "")
+  expect_equal(qty, 0)
+  qty <- osMaxPos(NULL, timestamp, 0, "", NULL, portfolio, symbol, "")
+  expect_equal(qty, 0)
+  qty <- osMaxPos(NULL, timestamp, 0, "", "short", portfolio, symbol, "")
+  expect_equal(qty, 0)
+  qty <- osMaxPos(NULL, timestamp, 0, "", NULL, portfolio, symbol, "")
+  expect_equal(qty, 0)
+})
+

Modified: pkg/quantstrat/tests/run-all.R
===================================================================
--- pkg/quantstrat/tests/run-all.R	2016-03-25 17:55:39 UTC (rev 1735)
+++ pkg/quantstrat/tests/run-all.R	2016-03-25 20:40:30 UTC (rev 1736)
@@ -1,5 +1,6 @@
 require(testthat)
 require(quantstrat)
 
-try(test_package("quantstrat", filter="paramsets"))
+test_package("quantstrat", filter="paramsets")
+test_package("quantstrat", filter="osMaxPos")
 



More information about the Blotter-commits mailing list