Skip to content

Possible bug in blotter

8 messages · Peter Carl, Wolfgang Wu, Brian G. Peterson

#
Consider the following example. Initialise portfolio on day 1 with 100 USD, buy 
stock ABC on day 2 at a price of 100, sell stock ABC on day 3 at a price of 100. 
Now the End.Eq in getAccount is showing 200 USD. 


library(blotter)
currency('USD')
stock('ABC', currency='USD', multiplier=1)
initPortf('portA', symbols="ABC", initDate='2010-01-01');
initAcct('accA',portfolios='portA', initDate='2010-01-01', initEq=100);
#Buy on day 2
addTxn("portA", Symbol='ABC', TxnDate='2010-01-02', TxnPrice=100, TxnQty = 1, 
TxnFees=0, verbose=TRUE)
currentPrice <- xts(100, order.by=as.Date('2010-01-02'))
updatePortf('portA', Dates = '2010-01-02', Prices=currentPrice)
updateAcct('accA', Dates = '2010-01-02')
updateEndEq('accA', Dates = '2010-01-02')
#Sell on day 3
addTxn("portA", Symbol='ABC', TxnDate='2010-01-03', TxnPrice=100, TxnQty = -1, 
TxnFees=0, verbose=TRUE)
currentPrice <- xts(100, order.by=as.Date('2010-01-03'))
updatePortf('portA', Dates = '2010-01-03', Prices=currentPrice)
updateAcct('accA', Dates = '2010-01-03')
updateEndEq('accA', Dates = '2010-01-03')
#Equity wrong?
getPortfolio('portA')
getAccount('accA') 

Wolfgang Wu
#
Wolfgang,

Your example is sending in prices in a way that blotter doesn't expect. 
I've modified your example to construct the price series that blotter can
work with.  We'll have to figure out a way to check the price series and
warn the user when it's mangled, so I appreciate the use case.

I've modified your script to construct a time series of prices for the
instrument being traded, ABC.  blotter uses FinancialInstrument to
associate the prices with the instrument, so that you don't have to.  I'd
refer you to the documentation, but we're still writing it...

library(blotter)
currency('USD')
stock('ABC', currency='USD', multiplier=1)
initPortf('portA', symbols="ABC", initDate='2010-01-01');
initAcct('accA',portfolios='portA', initDate='2010-01-01', initEq=100);
#Buy on day 2
addTxn("portA", Symbol='ABC', TxnDate='2010-01-02', TxnPrice=100, TxnQty =
1, TxnFees=0, verbose=TRUE)
ABC <- xts(100, order.by=as.Date('2010-01-02'))
colnames(ABC) = "Close"
updatePortf('portA', Dates = '2010-01-02')
updateAcct('accA', Dates = '2010-01-02')
updateEndEq('accA', Dates = '2010-01-02')
#Sell on day 3
addTxn("portA", Symbol='ABC', TxnDate='2010-01-03', TxnPrice=100, TxnQty =
-1, TxnFees=0, verbose=TRUE)
ABC <- rbind(ABC, xts(100, order.by=as.Date('2010-01-03')))
updatePortf('portA', Dates = '2010-01-03')
updateAcct('accA', Dates = '2010-01-03')
updateEndEq('accA', Dates = '2010-01-03')
#Equity wrong?
getPortfolio('portA')
getAccount('accA')

That results in:
$portfolios
$portfolios$portA
           Long.Value Short.Value Net.Value Gross.Value Realized.PL
2010-01-01          0           0         0           0           0
2010-01-02        100           0       100         100           0
2010-01-03          0           0         0           0           0
           Unrealized.PL Gross.Trading.PL Txn.Fees Net.Trading.PL
2010-01-01             0                0        0              0
2010-01-02             0                0        0              0
2010-01-03             0                0        0              0


$summary
           Additions Withdrawals Realized.PL Unrealized.PL Int.Income
2010-01-01         0           0           0             0          0
2010-01-02         0           0           0             0          0
2010-01-03         0           0           0             0          0
           Gross.Trading.PL Txn.Fees Net.Trading.PL Advisory.Fees
2010-01-01                0        0              0             0
2010-01-02                0        0              0             0
2010-01-03                0        0              0             0
           Net.Performance End.Eq
2010-01-01               0    100
2010-01-02               0    100
2010-01-03               0    100

attr(,"currency")
[1] "USD"
attr(,"initEq")
[1] 100
attr(,"class")
[1] "portfolio_account" "account"

... which is, I think, what you're looking for.

pcc
#
Peter, 

thank you for the explanation. I understand this now. However consider a 
different example where the security is now a futures contract with a multiplier 
of 2. Then blotter will produce a wrong End.Eq. (See example code) I suspect the 
Con.Mult column in the first row of the portfolio object is set wrongly and is 
causing the problem.  Would you agree?


library(blotter)
currency('USD')
future('ABC', currency='USD', multiplier=2, tick_size=1)
initPortf('portA', symbols="ABC", initDate='2010-01-01');
initAcct('accA',portfolios='portA', initDate='2010-01-01', initEq=100);
#Buy on day 2
addTxn("portA", Symbol='ABC', TxnDate='2010-01-02', TxnPrice=100, TxnQty =1, 
TxnFees=0, verbose=TRUE)
ABC <- xts(100, order.by=as.Date('2010-01-02'))
colnames(ABC) = "Close"
updatePortf('portA', Dates = '2010-01-02')
updateAcct('accA', Dates = '2010-01-02')
updateEndEq('accA', Dates = '2010-01-02')
#Sell on day 3
addTxn("portA", Symbol='ABC', TxnDate='2010-01-03', TxnPrice=100, TxnQty =-1, 
TxnFees=0, verbose=TRUE)
ABC <- rbind(ABC, xts(100, order.by=as.Date('2010-01-03')))
updatePortf('portA', Dates = '2010-01-03')
updateAcct('accA', Dates = '2010-01-03')
updateEndEq('accA', Dates = '2010-01-03')
#Equity wrong?
getPortfolio('portA')
getAccount('accA')


I then get the following result
$symbols
$symbols$ABC
$symbols$ABC$txn
           Txn.Qty Txn.Price Txn.Value Txn.Avg.Cost Pos.Qty Pos.Avg.Cost
2010-01-01       0         0         0            0       0            0
2010-01-02       1       100       200          100       1          100
2010-01-03      -1       100      -200          100       0            0
           Gross.Txn.Realized.PL Txn.Fees Net.Txn.Realized.PL Con.Mult
2010-01-01                     0        0                   0        0
2010-01-02                     0        0                   0        2
2010-01-03                     0        0                   0        2

$symbols$ABC$posPL
           Pos.Qty Con.Mult Ccy.Mult Pos.Value Pos.Avg.Cost Txn.Value
2010-01-01       0        1        1         0            0         0
2010-01-02       1        2        1       200          100       200
2010-01-03       0        2        1         0            0      -200
           Period.Realized.PL Period.Unrealized.PL Gross.Trading.PL Txn.Fees
2010-01-01                  0                    0                0        0
2010-01-02                  0                    0                0        0
2010-01-03                  0                  100              100        0
           Net.Trading.PL
2010-01-01              0
2010-01-02              0
2010-01-03            100

$symbols$ABC$posPL.USD
           Pos.Qty Con.Mult Ccy.Mult Pos.Value Pos.Avg.Cost Txn.Value
2010-01-01       0        1        1         0            0         0
2010-01-02       1        2        1       200          100       200
2010-01-03       0        2        1         0            0      -200
           Period.Realized.PL Period.Unrealized.PL Gross.Trading.PL Txn.Fees
2010-01-01                  0                    0                0        0
2010-01-02                  0                    0                0        0
2010-01-03                  0                  100              100        0
           Net.Trading.PL
2010-01-01              0
2010-01-02              0
2010-01-03            100



$summary
           Long.Value Short.Value Net.Value Gross.Value Period.Realized.PL
2010-01-03          0           0         0           0                  0
           Period.Unrealized.PL Gross.Trading.PL Txn.Fees Net.Trading.PL
2010-01-03                  100              100        0            100

attr(,"class")
[1] "blotter_portfolio" "portfolio"        
attr(,"currency")
[1] "USD"
attr(,"initDate")
[1] "2010-01-01"
$portfolios
$portfolios$portA
           Long.Value Short.Value Net.Value Gross.Value Realized.PL
2010-01-01          0           0         0           0           0
2010-01-02        200           0       200         200           0
2010-01-03          0           0         0           0           0
           Unrealized.PL Gross.Trading.PL Txn.Fees Net.Trading.PL
2010-01-01             0                0        0              0
2010-01-02             0                0        0              0
2010-01-03           100              100        0            100


$summary
           Additions Withdrawals Realized.PL Unrealized.PL Int.Income
2010-01-01         0           0           0             0          0
2010-01-02         0           0           0             0          0
2010-01-03         0           0           0           100          0
           Gross.Trading.PL Txn.Fees Net.Trading.PL Advisory.Fees
2010-01-01                0        0              0             0
2010-01-02                0        0              0             0
2010-01-03              100        0            100             0
           Net.Performance End.Eq
2010-01-01               0    100
2010-01-02               0    100
2010-01-03             100    200

attr(,"currency")
[1] "USD"
attr(,"initEq")
[1] 100
attr(,"class")
[1] "portfolio_account" "account"          



Thank you!

Regards, Wolfgang Wu
#
On 12/22/2010 04:30 AM, Wolfgang Wu wrote:
The first row doesn't have anything to do with it.  That row has a zero 
value, and is only there to initialize things.

It does appear that your example highlights a problem in the multiplier 
being applied to one of the Avg.Cost columns in the $posPL slot.

We'll investigate and fix.  Thanks for the report.

Regards,

   - Brian
#
I don't fully understand the code but the following patch fixes the problem for 
me. 


 tmpPL$Con.Mult.1 <- na.locf(tmpPL$Con.Mult.1)
 tmpPL$Con.Mult.1 <- ifelse(is.na(tmpPL$Con.Mult) & !is.na(tmpPL$Con.Mult.1) , 
tmpPL$Con.Mult.1, tmpPL$Con.Mult)
 tmpPL$Con.Mult <- na.locf(tmpPL$Con.Mult)
+tmpPL$Con.Mult <- na.locf(tmpPL$Con.Mult, fromLast=TRUE)
 tmpPL$Con.Mult <- ifelse(is.na(tmpPL$Con.Mult) ,1, tmpPL$Con.Mult)

There might be a more elegant solution however as I think it might be this bit 
of code quickly assumes that the multiplier is 1 when is.na == true

 tmpPL$Con.Mult <- ifelse(is.na(tmpPL$Con.Mult) ,1, tmpPL$Con.Mult) 

 Wolfgang Wu



----- Urspr?ngliche Mail ----
Von: Brian G. Peterson <brian at braverock.com>
An: r-sig-finance at r-project.org
Gesendet: Mittwoch, den 22. Dezember 2010, 13:43:24 Uhr
Betreff: Re: [R-SIG-Finance] Possible bug in blotter
On 12/22/2010 04:30 AM, Wolfgang Wu wrote:
The first row doesn't have anything to do with it.  That row has a zero value, 
and is only there to initialize things.

It does appear that your example highlights a problem in the multiplier being 
applied to one of the Avg.Cost columns in the $posPL slot.

We'll investigate and fix.  Thanks for the report.

Regards,

  - Brian

-- Brian G. Peterson
http://braverock.com/brian/
Ph: 773-459-4973
IM: bgpbraverock

_______________________________________________
R-SIG-Finance at r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-sig-finance
-- Subscriber-posting only. If you want to post, subscribe first.
-- Also note that this is not the r-help list where general R questions should 
go.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: updatePosPL.patch
Type: application/octet-stream
Size: 571 bytes
Desc: not available
URL: <https://stat.ethz.ch/pipermail/r-sig-finance/attachments/20101222/e196a0de/attachment.obj>
#
On 12/22/2010 08:06 AM, Wolfgang Wu wrote:
I've applied this patch in R-Forge SVN r506.

The 'better' method of NA handling would be to first check the contract 
multiplier in the instrument, but that will take more work to 
incorporate than your one-line patch.

As always, thanks for the report, test case, and patch.

I will try to incorporate your test case directly into the 'tests' for 
blotter soon so we can catch any regression or changes.

Regards,

   - Brian
1 day later
#
I am still bumping into problems trying to implement some of our trading 
strategies using blotter. So here is another one that seems to go wrong using 
r511.

library(blotter)
dateRange <- as.Date(as.Date('2010-01-02'):as.Date('2010-01-05'))
currency('USD')
stock('ABC', currency='USD')
ABC <- xts(102:105, order.by=dateRange)
colnames(ABC) = "Close"

initPortf('portA', symbols="ABC", initDate='2010-01-01');
initAcct('accA',portfolios='portA', initDate='2010-01-01', initEq=100);
addTxn("portA", Symbol='ABC', TxnDate='2010-01-02', TxnPrice=102, TxnQty =1, 
TxnFees=0, verbose=TRUE)
updatePortf('portA', Dates = dateRange)
updateAcct('accA', Dates = dateRange)
updateEndEq('accA', Dates = dateRange)
#Equity wrong?
getAccount('accA')



I get the following result with the End.Eq staying at 101 where I am expecting 
it to increase as the stock increases in value.

$portfolios
$portfolios$portA
           Long.Value Short.Value Net.Value Gross.Value Realized.PL
2010-01-01          0           0         0           0           0
2010-01-02        102           0       102         102           0
2010-01-03        103           0       103         103           0
2010-01-04        104           0       104         104           0
2010-01-05        105           0       105         105           0
           Unrealized.PL Gross.Trading.PL Txn.Fees Net.Trading.PL
2010-01-01             0                0        0              0
2010-01-02             0                0        0              0
2010-01-03             1                1        0              1
2010-01-04             1                1        0              1
2010-01-05             1                1        0              1


$summary
           Additions Withdrawals Realized.PL Unrealized.PL Int.Income
2010-01-01         0           0           0             0          0
2010-01-02         0           0           0             0          0
2010-01-03         0           0           0             1          0
2010-01-04         0           0           0             1          0
2010-01-05         0           0           0             1          0
           Gross.Trading.PL Txn.Fees Net.Trading.PL Advisory.Fees
2010-01-01                0        0              0             0
2010-01-02                0        0              0             0
2010-01-03                1        0              1             0
2010-01-04                1        0              1             0
2010-01-05                1        0              1             0
           Net.Performance End.Eq
2010-01-01               0    100
2010-01-02               0    100
2010-01-03               1    101
2010-01-04               1    101
2010-01-05               1    101

attr(,"currency")
[1] "USD"
attr(,"initEq")
[1] 100
attr(,"class")
[1] "portfolio_account" "account"          


Regards, Wolfgang Wu
#
On 12/24/2010 03:35 AM, Wolfgang Wu wrote:
This looks like a bug.  Looks like for some reason updateEndEq isn't 
accumulating the Trading.PL.  It's showing properly in the $posPL slot 
as Unrealized.PL and Trading.PL, so we'll have to sort out what's wrong 
with the equity calculation.

Thanks for the report, should be fixed at the latest early next week. 
As always, thank you for the reproducible test case, these always make 
debugging easier.

Also, for 'bug reports', it's generally considered best to email the 
maintainer of the package first, to not bother the list.  For 'help' or 
'support' requests, the list may be a better outlet, as others will 
likely have relevant experience and all benefit from sharing.

Regards,

   - Brian