[GSoC-PortA] Random Portfolios Speed Improvement with Rcpp
Ross Bennett
rossbennett34 at gmail.com
Fri Nov 15 19:47:40 CET 2013
Josh and Brian,
Thank you both for the detailed explanations. It went a long way helping me
understand how to improve the efficiency and performance of writing R code.
As a first step, I am going to add a formal "moments" argument to
constrained_objective. Once I have that working, I am going to take Josh's
suggestion of using environments. Using environments in this way is new
territory for me so I just want to make sure it works passing moments as an
argument.
Thanks again!
Ross
On Fri, Nov 15, 2013 at 5:40 AM, Joshua Ulrich <josh.m.ulrich at gmail.com>wrote:
> To clarify a point Brian made about how DEoptim creates the objective
> function call in C: it currently creates the call using the actual SEXP
> arguments, rather than their names, so it suffers from the same
> inefficiency that made quantstrat slow on large mktdata objects. Fixing
> this is on my to-do list.
>
> On Fri, Nov 15, 2013 at 4:51 AM, Brian G. Peterson <brian at braverock.com>wrote:
>
>> On 11/14/2013 10:25 PM, Ross Bennett wrote:
>>
>>> I think I found the culprit for the slow performance of
>>> constrained_objective. It has to do with the moments being re-calculated
>>> in set.portfolio.moments at each iteration of constrained_objective.
>>>
>>> You can verify this putting a print(str(momentargs)) or browser()
>>> statement at the beginning of set.portfolio.moments.
>>>
>>> Here is a small reproducible example to mimic how the moments are passed
>>> from optimize.portfolio to constrained_objective.
>>>
>>
>> Well, the whole point was always that those were to be calculated once
>> and then passed in.
>>
>> If that was somehow no longer happening (we did significantly rewrite a
>> lot of that code this year), then yes, it would really slow things down.
>>
>> <... code removed ...>
>>
>> Recalculating the moments will certainly slow things down, but
> optimize.portfolio will be faster still if it didn't pass the evaluated
> moment objects to the constrainted_objective function. This will be
> especially true for large portfolios. It currently calculates them and
> puts them in the dotargs list.
>
> optimize.portfolio.R:528
> mout <- try((do.call(momentFUN, .formals)) ,silent=TRUE)
> if(inherits(mout,"try-error")) {
> message(paste("portfolio moment function failed with message",mout))
> } else {
> dotargs <- mout
> }
>
> Then, as you note below, it passes dotargs as: ... = dotargs, which causes
> a problem.
>
> The most efficient solution would create a new environment and assign each
> element of mout to it, and then also assign any other objects
> the objective$name function needs to that same environment. Then you could
> evaluate the call to objective$name (with unevaluated arguments) in that
> environment.
>
> Look at quantstrat:::ruleProc as an example. I don't create a new
> environment in that case, but all the objects I need are in the environment
> of the function calling ruleProc. This is the change that provided a huge
> speed improvement when mktdata is very large.
>
> As an aside, you can easily see the actual call if you debug the function
> being called by do.call because it will print: debugging in: <printed
> call>. Unevaluated arguments will be represented by their name, while
> evaluated arguments will be represented by their deparsed contents.
>
>
>> > You can see that '...' is prepended when the list is constructed in
>> > fun2. This is why set.portfolio.moments can't find momentargs$mu,
>> > momentargs$sigma, etc. and has to be recalculated at each iteration.
>> > So the problem is '...' is actually the first element of the list.
>> >
>> > Have any of you run into this before? Any suggestions for a fix?
>> >
>>
> I've never run into this before, but the problem is that 'dotargs' is a
> list and the call sets '...' equal to dotargs. So '...' isn't a pairlist
> of 4 (mu, sigma, m3, m4); it's a pairlist of one list (dotargs). Your
> current solution of using the "reuse_moments" argument to control this will
> work, but it would be cleaner, more straight-forward, and more efficient to
> avoid it entirely like I describe above.
>
> > I think we could add a formal "moments" argument to constrained
>> > objective and pass the moments set in optimize.portfolio to
>> > constrained_objective directly through the "moments" argument. Is
>> > there any downside to this approach that I might be overlooking?
>>
>> No, this sounds like it should work. we control constrained_objective,
>> so being more explicit about what it receives should help.
>>
>> Thanks,
>>
>> Brian
>>
>>
>> --
>> Brian G. Peterson
>> http://braverock.com/brian/
>> Ph: 773-459-4973
>> IM: bgpbraverock
>>
>
> Best,
> --
> Joshua Ulrich | about.me/joshuaulrich
> FOSS Trading | www.fosstrading.com
>
>
>
> _______________________________________________
> GSoC-PortA mailing list
> GSoC-PortA at lists.r-forge.r-project.org
> http://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/gsoc-porta
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/gsoc-porta/attachments/20131115/9ffcf025/attachment.html>
More information about the GSoC-PortA
mailing list