[R-SIG-Finance] What are the requirements for instrument names in a blotter portfolio?

Brian G. Peterson brian at braverock.com
Wed Apr 28 13:11:28 CEST 2010


Robert,

I looks to me like you're on the right track.

It looks like the line that is failing is in updatePosPL (called from updatePortf).

I think I mentioned in one of my earlier messages that you won't get cumulative 
  P&L unless you have historical market price data available.  You're 
downloading a list of transactions from your broker, and adding those via 
addTxn().  That step is going fine.  The failure is later, when you call 
updatePortf().

Comment out this line:

portfolio = updatePortf(Portfolio = portfolio, Dates = CurrentDate)

and the script should import all your transactions properly and calculate 
transaction P&L on them.  You'll be able to verify this via getPortfolio(). 
chart.Posn() will also fail without historical market price data available.

To 'mark the book' it should make sense that you need historical price data. 
Any frequency is fine: tick, bars, daily close, etc.  updatePortf() will go 
find this data and calculate a 'mark' at each time point in your market data or 
against some reference index.  I typically run trades as irregular series, like 
yours, and then mark the book on some periodic basis, like hourly or daily.

If historical market data isn't available, then there's no point in calling 
updatePortf(), (and the Account and Equity functions) as there's nothing to 
calculate at the portfolio level.

I'm not at my main development machine today, but tomorrow I'll wrap the call 
to market data in a try() statement and add a more descriptive error so that 
hopefully it will be clearer to others what is required.

I suppose eventually we could 'mark the book' based only on the trade data, 
with no unrealized P&L changes not related to prices observed at the time of a 
trade, but I'll need to think about that a little more: I'm not sure it's worth 
the effort as I always have historical market data available.

Regards,

    - Brian

Robert Nicholson wrote:
> After I made the following changes I still seem to get the same error
> 
> [1] "2008-05-30 O24702R9GE 10 @ 0.35"
> Error in get(Symbol, envir = as.environment(.GlobalEnv)) : 
>   object 'O24702R9GE' not found
> 
> 
> The code prefixes any option that begins with a - with O and leaves equity stock symbols alone.
> 
> library(quantmod)
> library(blotter)
> library(PerformanceAnalytics)
> Transactions <- as.xts(read.zoo("/Users/robert/Downloads/transactions.csv", header=FALSE, FUN=as.POSIXct, sep=",", format="%m/%d/%Y"))
> colnames(Transactions) <- c('Action', 'Symbol', 'SecurityDescription', 'Cash', 'Quantity', 'Price', 'Commission', 'Fees', 'Blank', 'Amount', 'SettlementDate')
> 
> rm(list=ls(envir=.blotter),envir=.blotter)
> rm(list=ls(envir=.instrument),envir=.instrument)
> 
> USD = currency('USD')
> 
> Transactions$Symbol = sub('^[ ]','',Transactions$Symbol)
> 
> for (symbol in unique(Transactions$Symbol)) 
> {
> 	print (symbol)
> 	if (regexpr('^$', symbol) != -1) {
> 		print("ignore")
> 	} else if (regexpr('^-', symbol) == -1) {
> 		print("stock")
> 		stock(primary_id=symbol, currency='USD', multiplier = 1, underlying_id = NULL)
> 	} else if (regexpr('^-', symbol) != -1) {
> 		option(primary_id=sub('^[-]', 'O', symbol), currency='USD', multiplier = 100, underlying_id = NULL)
> 		print ("option")
> 	} else {
> 		print ("ignore")
> 	}
> }
> 
> Transactions$Symbol = sub('^[ -]+','O',Transactions$Symbol)
> 
> symbols = unique(Transactions$Symbol)
> 
> portfolioname = 'portfolio'
> accountname = 'account'
> 
> portfolio <- initPortf(portfolioname, symbols=symbols)
> account = initAcct(accountname, portfolios=portfolioname)
> for (i in 1:NROW(Transactions)) {
> 	Transaction = Transactions[i]
>         CurrentDate=time(Transaction)
> 	equity = getEndEq(account, CurrentDate)
>         symbol = Transaction$Symbol
>         price = as.numeric(Transaction$Price)
>         quantity = as.numeric(Transaction$Quantity)
>         if(is.na(Transaction$Fees)) {
>             fees = 0
>         } else {
>             fees = as.numeric(Transaction$Fees)
>         }
>         if (is.na(Transaction$Commission)) {
> 	    commission = 0
>         } else {
>             commission = as.numeric(Transaction$Commission)
>         }
> 	multiplier = 1
>         #if(substr(symbol,2,2) == '-') {
> 	#    multiplier = 100
> 	#}
> 	addTxn(Portfolio=portfolio, Symbol=symbol, TxnDate=CurrentDate, TxnPrice=(price*multiplier), TxnQty=quantity, TxnFees=(commission + fees), verbose=TRUE, ConMult=1)
> 	portfolio = updatePortf(Portfolio = portfolio, Dates = CurrentDate)
> }
> #portfolio = updatePortf(Portfolio = portfolio, Dates = CurrentDate)
> #account = updateAcct(Account = account, Dates = CurrentDate)
> #account = updateEndEq(Account = account, Dates = CurrentDate)
> 
> On Apr 26, 2010, at 9:11 AM, Brian G. Peterson wrote:
> 
>> I'll reply in more detail later if required, after US and European markets close, and try to work through the issue for you, but I'll give you a hint/direction now.
>>
>> I would probably start by defining the currency:
>>
>> currency('USD')
>>
>> and then once you read the transaction data, you already define the symbols here:
>>
>> symbols = as.character((unique(Transactions$Symbol)))
>>
>>
>> You could then define the instruments:
>>
>> for (symbol in symbols) {
>>    option(primary_id=symbol,currency='USD',multiplier='100')
>>    # you'd need more sophistication if either of the two constants above aren't true
>> }
>>
>> Ideally, since you're dealing with option series, you'd also define the option_series information, but that probably isn't necessary for downloaded trade P&L.  Jeff Ryan and I will likely do some work this spring on automatically defining the properties for options OSI symbology, but as I said, I don't think it is necessary in your case.  I typically load the instrument metadata from our internal databases (I think this is the most likely use-case right now for non-stock portfolios).
>>
>> Incidentally, I'd see if your broker can or will provide you the data using OSI standard symbols.  the symbols you've got in your data file don't contain a lot of information.
>>
>> updatePortf() will fail if you don't have market data for each symbol to mark the book on.  This may very well not be a problem for your stated purpose, as calling getPortfolio should allow you to view the per-trade P&L, and chart.Posn should work (but will not display cumulative P&L)
>>
>> Regards,
>>
>>     - Brian
>>
>> On 04/26/2010 08:49 AM, Robert Nicholson wrote:
>>> Sure here's an example
>>>
>>> Please bear I'm in mind I'm still learning R and blotter.
>>>
>>> The idea is to put transaction data thru and then look at the PnL ideally for each trade
>>>
>>> The transactions file looks like this for each row
>>>
>>> 05/30/2008, YOU BOUGHT           OPENING TRANSACTION, -24702R9GE, CALL (DLQ) DELL INC JUL 25 (100 SHS),Cash,10,0.35,17.5,,,-367.5, 06/02/2008
>>> 06/12/2008, YOU SOLD             CLOSING TRANSACTION, -24702R9GE, CALL (DLQ) DELL INC JUL 25 (100 SHS),Cash,-10,0.56,18.45,,,541.54, 06/13/2008
>>>
>>> library(quantmod)
>>> library(blotter)
>>> library(PerformanceAnalytics)
>>> Transactions<- as.xts(read.zoo("/Users/robert/Downloads/transactions.csv", header=FALSE, FUN=as.POSIXct, sep=",", format="%m/%d/%Y"))
>>> colnames(Transactions)<- c('Action', 'Symbol', 'SecurityDescription', 'Cash', 'Quantity', 'Price', 'Commission', 'Fees', 'Blank', 'Amount', 'SettlementDate')
>>>
>>> Transactions$Symbol = sub('[ -]*','INST',Transactions$Symbol)
>>>
>>> symbols = as.character((unique(Transactions$Symbol)))
>>> portfolioname = 'portfolio'
>>> accountname = 'account'
>>>
>>> rm(list=ls(envir=.blotter),envir=.blotter)
>>>
>>> portfolio<- initPortf(portfolioname, symbols=symbols)
>>> account = initAcct(accountname, portfolios=portfolioname)
>>> for (i in 1:NROW(Transactions)) {
>>> 	Transaction = Transactions[i]
>>>         CurrentDate=time(Transaction)
>>> 	equity = getEndEq(account, CurrentDate)
>>>         symbol = Transaction$Symbol
>>>         price = as.numeric(Transaction$Price)
>>>         quantity = as.numeric(Transaction$Quantity)
>>>         if(is.na(Transaction$Fees)) {
>>>             fees = 0
>>>         } else {
>>>             fees = as.numeric(Transaction$Fees)
>>>         }
>>>         if (is.na(Transaction$Commission)) {
>>> 	    commission = 0
>>>         } else {
>>>             commission = as.numeric(Transaction$Commission)
>>>         }
>>> 	multiplier = 1
>>>         if(substr(symbol,2,2) == '-') {
>>> 		multiplier = 100
>>> 	}
>>> 	addTxn(Portfolio=portfolio, Symbol=symbol, TxnDate=CurrentDate, TxnPrice=(price*multiplier), TxnQty=quantity, TxnFees=(commission + fees), verbose=TRUE, ConMult=1)
>>> 	portfolio = updatePortf(Portfolio = portfolio, Dates = CurrentDate)
>>> }
>>> #portfolio = updatePortf(Portfolio = portfolio, Dates = CurrentDate)
>>> #account = updateAcct(Account = account, Dates = CurrentDate)
>>> #account = updateEndEq(Account = account, Dates = CurrentDate)
>>>
>>> On Apr 26, 2010, at 8:40 AM, Brian G. Peterson wrote:
>>>
>>>   
>>>> As should be clear from the documentation and examples, we have followed the 'quantmod' convention of storing the market data as the symbol name.
>>>>
>>>> My presumtion is that as you could not possibly have stored your market data as '-24702R9GE' (as this is an illegal R variable name), you have likely also not stored it as 'INST24702R9GE'
>>>>
>>>> The call that is failing, however, suggests a different problem.
>>>>
>>>> This error:
>>>>
>>>> Error in get(x, pos = .instrument) : object 'INST24702R9GE' not found
>>>>
>>>> suggests that you haven't declared the instrument, with currency, multiplier, etc.
>>>>
>>>> it's not clear if the next error is directly related, or if it is simply the code falling back to try to find the instrument data in the global environment.
>>>>
>>>> Diagnosing this would be much easier if you provided a complete, reproducible example, per the posting guide.  Then I wouldn't have to guess, I could simply run the code.
>>>>
>>>> Regards,
>>>>
>>>>     - Brian
>>>>
>>>> On 04/26/2010 08:32 AM, Robert Nicholson wrote:
>>>>     
>>>>> Why then do I get this?
>>>>>
>>>>> I added
>>>>>
>>>>> Transactions$Symbol = sub('[ -]*','INST',Transactions$Symbol)
>>>>>
>>>>> so this prefixes everything I had with INST presumably I can have digits in the name
>>>>>
>>>>> 1] "2008-05-30 INST24702R9GE 10 @ 0.35"
>>>>> Error in get(x, pos = .instrument) : object 'INST24702R9GE' not found
>>>>> Error in get(Symbol, envir = as.environment(.GlobalEnv)) :
>>>>>   object 'INST24702R9GE' not found
>>>>>
>>>>>
>>>>> On Apr 26, 2010, at 5:01 AM, Brian G. Peterson wrote:
>>>>>
>>>>>
>>>>>       
>>>>>> R variable names may not start with a number.
>>>>>>
>>>>>> instruments will be used to create R variables, so all normal naming rules for variables apply.
>>>>>>
>>>>>> Robert Nicholson wrote:
>>>>>>
>>>>>>         
>>>>>>> Why when
>>>>>>> names(getPortfolio(portfolio))
>>>>>>>  [1] " -24702R9GE"
>>>>>>> do I have
>>>>>>> [1] "2008-05-30  -24702R9GE 10 @ 35"
>>>>>>> Error in get(x, pos = .instrument) : object ' -24702R9GE' not found
>>>>>>> Error in get(Symbol, envir = as.environment(.GlobalEnv)) :   object ' -24702R9GE' not found
>>>>>>> when I call
>>>>>>> 	portfolio = updatePortf(Portfolio = portfolio, Dates = CurrentDate)
>>>>>>>
>>>>>>>           
>>>>>> -- 
>>>>>> Brian G. Peterson
>>>>>> http://braverock.com/brian/
>>>>>> Ph: 773-459-4973
>>>>>> IM: bgpbraverock
>>>>>>
>>>>>>         
>>>> -- 
>>>> Brian G. Peterson
>>>> http://braverock.com/brian/
>>>> Ph: 773-459-4973
>>>> IM: bgpbraverock
>>>>
>>>>
>>>>     
>>
>> -- 
>> Brian G. Peterson
>> http://braverock.com/brian/
>> Ph: 773-459-4973
>> IM: bgpbraverock
>>
>>


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



More information about the R-SIG-Finance mailing list