Log in to see Cloud of Tags

Wealth-Lab Wiki

WealthScript Techniques | MultiSystem, or Calling a Strategy From Another

RSS

Note:

This article saw the light before Wealth-Lab 6.2 started providing effortless multiple system (and even multiple portfolio) backtesting via Combination Strategy interface. We highly recommend to explore this new feature.

Still, this design pattern of several Strategies in the same script may be useful in two cases which are out of scope for the architecture of Combination Strategies:

  • If you need the Combo strategies to interact and thus influence trading decisions in another strategy
  • If the Combo strategy equity should be constantly readjusted on a day-to-day basis with regard to the "Percent of Starting Equity" allocation

The problem

Is there a way to programmatically call one strategy from another?

The approach

There are two possible known ways to "call" a strategy.

The first is outlined in our Wiki KB article, Interacting Dynamically with Portfolio Level Equity, and includes making a call to the undocumented method TradingSystemExecutor. This is approximately how Wealth-Lab itself executes a strategy internally. Since it's unsupported, you can download the source code for Community.Components and dig deeper into Utility.cs class which contains all the code.

The other one is more straightforward and can be easily used to create a primitive "multi-system" Strategy:

Code examples

Notice a workaround that closes all positions which are still left open on the last bar:

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;

namespace WealthLab.Strategies { public class Multisystem : WealthScript { protected override void Execute() { System1.Run(this); System2.Run(this); } } class System1 { public static void Run(WealthScript obj) { for(int bar = 20; bar < obj.Bars.Count; bar++) { if (obj.IsLastPositionActive) { obj.SellAtStop( bar+1, obj.LastPosition, Lowest.Series( obj.Low,10 )[bar] ); } else { obj.BuyAtStop( bar+1, Highest.Series( obj.High,20 )[bar], "System1" ); } // Workaround to prevent open positions from one system to be available for the next system to close if( bar == obj.Bars.Count-1 ) obj.SellAtClose( bar, Position.AllPositions, "Close All" ); } } } class System2 { public static void Run(WealthScript obj) { for(int bar = 20; bar < obj.Bars.Count; bar++) { if (obj.IsLastPositionActive) { obj.SellAtMarket( bar+1, obj.LastPosition ); } else { obj.BuyAtLimit( bar+1, obj.Low[bar]*0.95, "System2" ); }

// Workaround to prevent open positions from one system to be available for the next system to close if( bar == obj.Bars.Count-1 ) obj.SellAtClose( bar, Position.AllPositions, "Close All" ); } } } }

Below is a more advanced example that builds upon the code above.

  1. For improved performance the systems are run in multiple threads, not sequentially.
  2. To communicate between the two systems, you could pass shared objects by reference as parameters such that each task gets his own object by "ref" and the other does not (suggested by Wealth-Lab user Mark Mehl):


...
using System.Threading.Tasks; // <- run the subsystems in multiple threads via Task

public class Multisystem : WealthScript { protected override void Execute() { Task.Run(() => System1.Run(this, ref sharedObj1, sharedObj2)); Task.Run(() => System2.Run(this, sharedObj1, ref sharedObj2)); } } ...

Important Disclaimer: The information provided by Wealth-Lab is strictly for informational purposes and is not to be construed as advice or solicitation to buy or sell any security.  The owner of Wealth-Lab.com assumes no liability resulting from the use of the material contained herein for investment purposes. By using this web site, you agree to the terms of this disclaimer and our Terms of Use.


ScrewTurn Wiki. Some of the icons created by FamFamFam.