[R-SIG-Finance] Simulated expected return for a hedge fund

G See gsee000 at gmail.com
Sun Dec 25 21:25:33 CET 2011


Hi David,

2 things.  First, the second term of your expected profit expression
should have a positive sign.  i.e.
mean(above)*mean(profit.above) + mean(below)*mean(profit.below) +
mean(between)*mean(profit.between)

Second, your expected profit calculation does not take into account
how many days it took you to earn/lose that money.  If you do that,
our answers agree

> prof.above <- profit.above/above.ending.day
> prof.below <- profit.below/below.ending.day
> prof.between <- profit.between/100
> mean(above)*mean(prof.above) + mean(below)*mean(prof.below) + mean(between)*mean(prof.between)
[1] -1098.853

However, just because our answers agree doesn't mean they are right.
:-)  I would be interested to learn what answer the author came up
with.

Cheers,
Garrett

On Sun, Dec 25, 2011 at 1:45 PM, Afshartous, David
<d.afshartous at vanderbilt.edu> wrote:
>
> Hi Garrett,
>
> Thanks for looking into the problem.   You are correct, one has to be careful to note that portfolio value for early sells will not be exactly equal to the boundary values that trigger the early sells (and also that -100% loss conversion to daily return is an issue).
>
> I corrected my code and now obtain the same expected return as your code to within 5 decimal places.   However, I still obtain a positive value for the expected profit.  My calculation is a conditional probability calculation whereas your calculation is direct.   I doubt that such big difference in expected profit could be due to rounding error of such a process but at the same time we obtain the same expected return.    Code below:
>
> niter = 10000     ## number of iterations
> below = rep(0, niter)   ## set up storage
> above = rep(0, niter)
> between = rep(0, niter)
> between.ending.value = NULL
> below.ending.day = NULL
> above.ending.day = NULL
> profit.above = NULL
> profit.below = NULL
> profit.between = NULL
> set.seed(2009)
> for (i in 1:niter) {
>  r = rnorm(100, mean = .05/253, sd = .23/sqrt(253))
>  logPrice = log(1e6) + cumsum(r)  ## 1e6 = initial price
>  minLogP = min(logPrice)  ## min price over next 45 days
>  maxLogP = max(logPrice)  ## min price over next 45 days
>  crossBelowLogP.day = ifelse( minLogP < log(950000),  min(which(logPrice < log(950000))), 101) ## 101 means doesn't cross
>  crossAboveLogP.day = ifelse( maxLogP > log(1100000),  min(which(logPrice > log(1100000))), 101)
>  if ( (minLogP >= log(950000)) & (maxLogP <= log(1100000)) ) {   ## Neither cross boundary
>     between[i] = 1
>     between.ending.value = append(between.ending.value, exp(logPrice[100]))
>     profit.between =   append(profit.between, between.ending.value - 1000000)
>     }
>  if  ( (minLogP < log(950000)) & (maxLogP > log(1100000))) { ## Both cross
>             ifelse (crossBelowLogP.day < crossAboveLogP.day, below[i] <- 1, above[i] <-1)
>             ifelse (crossBelowLogP.day < crossAboveLogP.day, below.ending.day <- append(below.ending.day, crossBelowLogP.day),
>                                                        above.ending.day <- append(above.ending.day, crossAboveLogP.day))
>             ifelse (crossBelowLogP.day < crossAboveLogP.day, profit.below <-   append(profit.below, exp(logPrice[crossBelowLogP.day]) - 1000000),
>                                                        profit.above  <-      append(profit.above, exp(logPrice[crossAboveLogP.day]) - 1000000))
>           }
>  if ( (minLogP < log(950000))  & (maxLogP <= log(1100000))  ) {    ## Only cross below
>             below[i] = 1
>             below.ending.day = append(below.ending.day, crossBelowLogP.day)
>             profit.below =   append(profit.below, exp(logPrice[crossBelowLogP.day]) - 1000000)
>           }
>  if ( (minLogP >= log(950000))  & (maxLogP > log(1100000))  ) {    ## Only cross above
>             above[i] = 1
>             above.ending.day = append(above.ending.day, crossAboveLogP.day)
>             profit.above =  append(profit.above, exp(logPrice[crossAboveLogP.day]) - 1000000)
>           }
> }
>
> ## expected profit
> mean(above)*mean(profit.above) - mean(below)*mean(profit.below) + mean(between)*mean(profit.between)
> [1] 77227.87
>
>
> ret.above = (profit.above/50000)/above.ending.day  ## daily return, return wont' be exactly 1 since P_t won't be exactly equal to 100,000
> ret.below = (profit.below/50000)/below.ending.day  ## daily return
> ret.between = (profit.between/50000)/100  ## daily return
> ## exp.return:
> mean(above)*mean(ret.above)   + mean(below)*mean(ret.below)   + mean(between) * mean(ret.between)
> [1] -0.02197705
>
>
> ________________________________________
> From: G See [gsee000 at gmail.com]
> Sent: Sunday, December 25, 2011 12:44 PM
> To: Afshartous, David
> Subject: Re: [R-SIG-Finance] Simulated expected return for a hedge fund
>
> BTW,
>
> I get a negative value for expected Profit also
>
>> niter = 10000     ## number of iterations
>> set.seed(2009)
>> PnLs <- rep(0, niter)
>> for (i in 1:niter) {
> +     r = rnorm(100, mean = .05/253, sd = .23/sqrt(253))
> +     SV <- 1e6 * exp(cumsum(r)) #StockValue
> +     daily.PnL <- if (min(SV) > 950000 && max(SV) < 1100000) {
> +         #between
> +         SellPrice <- tail(SV, 1) # Sell on last day (100 returns in
> the future)
> +         PnL <- (SellPrice - 1000000)
> +         PnL / 100  # average daily PnL
> +     } else {
> +         # Sell at first value that is less than 950000 or greater than 1100000
> +         SellPrice <- head(SV[SV < 950000 | SV > 1100000], 1)
> +         days.held <- head(which(SV == SellPrice), 1) # first place
> that StockValue equals SellPrice
> +         #if (SellPrice < 950000) SellPrice <- 950000
> +         PnL <- (SellPrice - 1000000)
> +         PnL / days.held
> +     }
> +     PnLs[i] <- daily.PnL
> + }
>> mean(PnLs)
> [1] -1098.661
>> mean(PnLs) / 50000
> [1] -0.02197322
>>
>
>
> On Sat, Dec 24, 2011 at 10:31 PM, G See <gsee000 at gmail.com> wrote:
>> David,
>>
>> I attempted to work the problem myself, and have concluded that it is
>> a poor question. :-P
>> The question says that you will sell for a profit of _at least_
>> $100,000, if the value of the stock
>> rises to at least $1,100,000 or sell for a loss if the value falls
>> below $950000.
>>
>> I interpret that to mean that on the first day that the stock value is
>> at or above 1.1 million, I sell
>> at the prevailing price (which may, and probably will, be higher than
>> 1.1 million).  Likewise, I think
>> it says that I will sell on the first day that the value of the stock
>> is below $950,000.  But, if the
>> stock gets to $950,000, I'm out of capital.  It is unlikely that the
>> value of the stock will be
>> exactly $950,000, which means that I would be losing more than 100
>> percent of my capita.  I
>> don't know how to convert an N-day return that is less than negative
>> 100 percent to either a daily
>> or annual return.  So, I just divided it by the number of days.  i.e.
>> if you lose 110% over 10 days
>> then you're losing 11% per day on average. (But, I'm aware that that
>> doesn't make sense)
>>
>> My attempt is below; I came up with an "answer" of -0.02197322
>>
>>
>> niter = 10000     ## number of iterations
>> set.seed(2009)
>> returns <- rep(0, niter)
>> for (i in 1:niter) {
>>     r = rnorm(100, mean = .05/253, sd = .23/sqrt(253))
>>     SV <- 1e6 * exp(cumsum(r)) #StockValue
>>     daily.ret <- if (min(SV) > 950000 && max(SV) < 1100000) {
>>         #between
>>         SellPrice <- tail(SV, 1) # Sell on last day (100 returns in the future)
>>         ret <- (SellPrice - 1000000) / 50000
>>         ret / 100  # average daily return
>>     } else {
>>         # Sell at first value that is less than 950000 or greater than 1100000
>>         SellPrice <- head(SV[SV < 950000 | SV > 1100000], 1)
>>         days.held <- head(which(SV == SellPrice), 1) # first place
>> that StockValue equals SellPrice
>>         #if (SellPrice < 950000) SellPrice <- 950000
>>         ret <- (SellPrice - 1000000) / 50000
>>         ret / days.held
>>     }
>>     returns[i] <- daily.ret
>> }
>> mean(returns)
>> # -0.02197322
>>
>> HTH,
>> Garrett
>>
>>
>> On Sat, Dec 24, 2011 at 5:51 PM, Afshartous, David
>> <d.afshartous at vanderbilt.edu> wrote:
>>>
>>>
>>> Thanks Garrett.  I fixed that typo and also put the conditional returns in terms of daily returns and the answer now seems reasonable.   The changes to the code are:
>>>
>>> ret.above = 1/above.ending.day  ## daily return
>>> ret.below = -1/below.ending.day
>>>
>>> ret.between = net/100
>>>
>>> which now yields:
>>> exp.return = mean(above)*mean(ret.above)   + mean(below)*mean(ret.below)   + mean(between) * mean(ret.between)
>>> > exp.return
>>> [1] -0.03455923
>>>
>>> Interesting, since the expected profit is positive:
>>>
>>> exp.profit = mean(above)*100000 - mean(below)*50000 + mean(between)*(mean(between.ending.value) - 1000000)
>>> > exp.profit
>>> [1] 7530.114
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>> ________________________________________
>>> From: G See [gsee000 at gmail.com]
>>> Sent: Saturday, December 24, 2011 1:27 PM
>>> To: Afshartous, David
>>> Cc: r-sig-finance at r-project.org
>>> Subject: Re: [R-SIG-Finance] Simulated expected return for a hedge fund
>>>
>>> I'm not at a computer, but it looks like if the account value falls from 50,000 to zero, you are counting that as a 0% return instead of -100%?
>>>
>>> On Dec 24, 2011 12:58 PM, "G See" <gsee000 at gmail.com<mailto:gsee000 at gmail.com>> wrote:
>>>
>>> Sorry, please disregard. I didn't look at your code closely.
>>>
>>> On Dec 24, 2011 10:55 AM, "G See" <gsee000 at gmail.com<mailto:gsee000 at gmail.com>> wrote:
>>> Hi David,
>>>
>>> Here is my hint:
>>>
>>> 1> set.seed(2009)
>>> 1>  r = rnorm(100, mean = .05/253, sd = .23/sqrt(253))
>>> 1>  logPrice = log(1e6) + cumsum(r)  ## 1e6 = initial price
>>> 1> logPrice
>>>  [1] 13.80340 13.80755 13.80516 13.80164 13.82105 13.79453 13.79750 13.80408 13.78316 13.77246 13.77529
>>>  [12] 13.79100 13.78908 13.79427 13.79268 13.76960 13.78917 13.79897 13.80548 13.80673 13.83131 13.82956
>>>  [23] 13.82829 13.83970 13.84860 13.88746 13.90191 13.89439 13.88666 13.89621 13.92104 13.91894 13.92787
>>>  [34] 13.91217 13.90804 13.91452 13.92865 13.95498 13.98419 13.98820 13.99140 14.00165 13.97519 13.96530
>>>  [45] 13.95029 13.95800 13.94906 13.94807 13.91299 13.90617 13.90202 13.90779 13.89517 13.88682 13.89177
>>>  [56] 13.88537 13.89815 13.87475 13.86916 13.88294 13.87048 13.86705 13.87571 13.86564 13.85744 13.87504
>>>  [67] 13.88990 13.88075 13.87261 13.86023 13.85191 13.85510 13.84572 13.84649 13.85447 13.83746 13.82143
>>>  [78] 13.80111 13.78505 13.79430 13.81151 13.81456 13.80200 13.79527 13.80288 13.76598 13.79024 13.81018
>>>  [89] 13.80240 13.77962 13.78402 13.78493 13.80514 13.79839 13.77328 13.78443 13.78491 13.77488 13.75898
>>> [100] 13.74589
>>>
>>> That's probably not what you intended ;-)
>>>
>>> Garrett
>>>
>>> On Fri, Dec 23, 2011 at 2:43 PM, Afshartous, David <d.afshartous at vanderbilt.edu<mailto:d.afshartous at vanderbilt.edu>> wrote:
>>>
>>> All,
>>> Below is an R-lab problem from Ch2 of Statistics and Data Analysis for Financial Engineering (Ruppert, 2010).   The R code runs okay but the answer seems strange.   Any hints much appreciated.
>>> Cheers,
>>> David
>>>
>>> David Afshartous, Ph.D.
>>> Research Associate Professor
>>> PSTAT®: ASA Accredited Professional Statistician
>>> Department of Biostatistics
>>> Vanderbilt University Medical Center
>>>
>>>
>>> ## suppose Hedge fund owns $1,000,000 of stock and used $50,000 capital and
>>> ## $950,000 borrowed money for the purchase.
>>> ## Daily log returns on the stock have a mean of 0.05/year and SD of 0.23/year,
>>> ## which can be converted to per trading day by dividing by 253 and sqrt(253)
>>>
>>> ## the hedge fund will sell the stock for a profit of at least $100,000 if the value
>>> ## of the stock rises to at least $1,100,000 at the end of one of the first 100 trading days,
>>> ## sell it for a loss if the value falls below $950,000 at the end of one of the first
>>> ## 100 trading days, or sell after 100 trading days if the closing price has stayed between
>>> ## $950,000 and $1,1000,000.
>>>
>>> ## PROBLEM 7: What is the expected return? When answering this question, remember
>>> ## that only $50,000 was invested.  Also, the units of return are time, e.g.,
>>> ## one can express a return as a daily return or a weekly return.  Therefore,
>>> ## one must keep track of how long the hedge fund holds its position before selling
>>>
>>> The code below simulates whether value falls below 950,000, goes above 1,1000,000, or stays between. The amount lost/gained in the 1st/2nd scenario is a constant, whereas the amount lost/gained in the third scenario is random.
>>>
>>> ### simulation code; written for readability as opposed to speed
>>> niter = 10000     ## number of iterations
>>> below = rep(0, niter)   ## set up storage
>>> above = rep(0, niter)
>>> between = rep(0, niter)
>>> between.ending.value = NULL
>>> below.ending.day = NULL
>>> above.ending.day = NULL
>>> set.seed(2009)
>>> for (i in 1:niter) {
>>>  r = rnorm(100, mean = .05/253, sd = .23/sqrt(253))
>>>  logPrice = log(1e6) + cumsum(r)  ## 1e6 = initial price
>>>  minLogP = min(logPrice)  ## min price over next 45 days
>>>  maxLogP = max(logPrice)  ## min price over next 45 days
>>>  crossBelowLogP.day = ifelse( minLogP < log(950000),  min(which(logPrice < log(950000))), 101) ## 101 means doesn't cross
>>>  crossAboveLogP.day = ifelse( maxLogP > log(1100000),  min(which(logPrice > log(1100000))), 101)
>>>  if ( (minLogP >= log(950000)) & (maxLogP <= log(1100000)) ) {   ## Neither cross boundary
>>>    between[i] = 1
>>>    between.ending.value = append(between.ending.value, exp(logPrice[100]))
>>>    }
>>>  if  ( (minLogP < log(950000)) & (maxLogP > log(1100000))) { ## Both cross
>>>            ifelse (crossBelowLogP.day < crossAboveLogP.day, below[i] <- 1, above[i] <-1)
>>>            ifelse (crossBelowLogP.day < crossAboveLogP.day, below.ending.day <- append(below.ending.day, crossBelowLogP.day),
>>>                                                       above.ending.day <- append(above.ending.day, crossAboveLogP.day))
>>>          }
>>>  if ( (minLogP < log(950000))  & (maxLogP <= log(1100000))  ) {    ## Only cross below
>>>            below[i] = 1
>>>            below.ending.day = append(below.ending.day, crossBelowLogP.day)
>>>          }
>>>  if ( (minLogP >= log(950000))  & (maxLogP > log(1100000))  ) {    ## Only cross above
>>>            above[i] = 1
>>>            above.ending.day = append(above.ending.day, crossAboveLogP.day)
>>>          }
>>> }
>>> mean(above)  ## this will give the probability of the value crossing the above threshold
>>>
>>> When annualizing returns, the day in which a boundary needs to be accounted for.    The following code calculates the overall expected return by conditioning on each scenario:
>>>
>>> # cross above: always make constant 100,000 based on initial investment of 50,000
>>> # P_t/P_t-1 = 100,000/50,000 = 2 = gross return --> net return = 2 - 1 = 1
>>> ret.above = (1 + 1)^(365/(above.ending.day))  - 1    ### annualized
>>>
>>> # cross below: always lose constant 50,000 based on initial investment of 50,000
>>> # P_t/P_t-1 = 50,000/50,000 = 1 = gross return --> net return = 1 - 1 = 0
>>> ret.below = 0
>>>
>>> ## betwen: final value depends on realized value on 100th day
>>> # P_t/P_t-1 = between.ending.value/50,000 = --> net return = gross return  - 1
>>>
>>> net = ifelse(between.ending.value < 1000000,
>>>                   (1000000 - between.ending.value)/50000 - 1,  ## net return, gain
>>>                   (between.ending.value  - 1000000)/50000 - 1)   ## net return, loss
>>>
>>> ret.between = (1 + net)^(365/100) - 1
>>>
>>> exp.return = mean(above)*mean(ret.above)   + mean(below)*mean(ret.below)   + mean(between) * mean(ret.between)
>>> 8.669104e+50???
>>>
>>> _______________________________________________
>>> R-SIG-Finance at r-project.org<mailto: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.
>>>
>>>
>
>



More information about the R-SIG-Finance mailing list