Combination strategies
While single strategy backtest reports errors in the debug window, Combination Strategy does not proceed with the testing.The design is abort strategy processing when an error is detected. Fix the error or wrap the original strategy code in a try/catch block.
Is child strategy equity being constantly readjusted on a day-to-day basis with regard to the "Percent of Starting Equity" allocation?No. "Percent of
Starting Equity" is used to allocate the specified amount of
starting equity, and afterwards each strategy is confined to its individual allocation.
Rule-based strategies
The condition list for Date/Time only includes conditions for dates. How do I include a "time of the day" rule?Either use the
"Intraday Rule: Time is later (earlier) than HHmm" in
Community.Rules library or see a tip in the
WealthScript section below.
After generating strategy code with "View Strategy Code", there are strings like "Group1" and "Group1|". What do they mean?This is a string used to match up entries with exits. From the technical standpoint, the
String.Contains(string) method does the job here.
Is it possible to add an ATR-based Trailing stop in Rule-based Strategy?Presently, the Rule-based Wizard lacks ATR Trailing stops. Nonetheless, this is pretty easy to do in code-based Strategy: just follow the QuickRef entry for
HighestHighAsOfBar as an example.
How to create a pullback setup in Rule-based Strategy?Problem:
You want to be able to create
a Pullback in an Uptrend entry. For instance, in an established uptrend, wait for a three bar pullback and
enter at stop $0.10 above prior bar high. However, the Rule Wizard doesn't seem to have "Buy at Stop" rule desired.
Solution:
You can get pretty close by starting with these rules:
BuyAtLimit (High)
- Moving Average is trending up (Moving Average group)
- Price decreases a consecutive number of bars (Price (or Volume) group)
..and add an exit (if you only want a screen, see
Techniques > Creating a Screener in the WealthScript Programming Guide),
After that, you'll need to "Open Code in new Strategy Window" and make the following edit:
// IS:
BuyAtLimit(bar + 1, Highbar, "");
// CHANGE TO:
BuyAtStop(bar + 1, Highbar + 0.10, "");
I'm not able to edit the optimization parameters (Default, Start, End, Increment) in the Optimization Control tab for rule-driven strategies.It's locked for rule-based strategies by design. You will have to "Convert to code-based strategy" or "Open Strategy code in new window".
For advanced users, an
unsupported workaround implies editing of the Strategy's XML file.
How to create a stop-and-reverse system in a Rule-based Strategy?Problem:
Is it possible to create a stop-and-reverse system in the Rule Wizard?
Solution:
The Stop-And-Reverse option which existed in legacy versions of Wealth-Lab was removed for the purpose of simplification. However, there is a workaround: selecting
"Multiple open positions allowed" will let you switch from long to short position on the same bar.
Limitation: this trick won't work when adding multiple conditions, only for a single symmetric condition.
The solution is to create a SAR system manually:
WealthScript Techniques | Creating a Stop-And-Reverse (SAR) system
Indicators
I get a difference between the ATR calculation of Wealth-Lab and my own calculation.Most likely, your calculation is treating
ATR as an arithmetic average. It's
not: the ATR formula uses Wilder's smoothing method (
WMA). Check out the proper
ATR formula in this Wiki.
How do I create MACD indicator with custom parameters?Two solutions:
- On-the-fly:
See Help > WealthScript Programming Guide > Indicators > Custom Indicators > "How to: Create a MACD with Custom Periods".
- As a full-blown indicator, accessible by rule-based strategies:
Install the Community.Indicators library which includes MACD with custom parameters.
Why in many channel-breakout codes is it correct to shift the series forward by one bar (i.e. >>1) ?The reason to shift (delay) the series like this...
DataSeries s = Lowest.Series(Close, period) >> 1
...is that on the chart, it's visually pleasing to see prices "crossing over/under" a plotted line.
Is it possible to plot several drag & drop indicators in one shot?No. There hardly is any advantage to showing a new dialog with a large list of indicators that still must be configured individually. Instead, drag and drop indicators until you feel satisified and then save the "strategy" which can in future be reopened to modify any of these indicators by double clicking. On the other hand, creating a code-based strategy will work just fine for this task.
Is it possible to import custom indicator data calculated outside Wealth-Lab?Of course. There are two options:
- The most convenient way is to use FillSeriesFromFile method from Community Components library
- Create an ASCII DataSet of the indicator directory, and access it as if it were a secondary symbol
Rotation strategies
A Rotation strategy isn't working like it should.Symptoms:
- Trades are taken multiple times: the same stock can be purchased 3 or 4 times. There are 1000's of trades reported missing from the simulation etc.
- The By Symbol tab bears no resemblance to the Performance tab.
Solution:
Read the Strategy description. Follow the usage notes precisely. Select only 1 symbol in the DataSet. This strategy should not be run in Multi-Symbol Backtest mode. Otherwise you'll be running the script once for each symbol, and it's not designed for that.
Rotational systems are incompatible with such visualizers as By Symbol and Analysis Series.
My code with DataSetSymbols runs incorrectly or can't run on more than a few symbols.Check that you're
not running it on the DataSet. You should never run a strategy with a DataSetSymbols loop on the entire DataSet - it just doesn't make sense to do that. You'll end up running the same code
DataSetSymbols * DataSetSymbols times! Run such code for just one symbol in the DataSet.
Why there are different results depending on the clicked symbol?The only way the results will be the same is if all the data are synchronized natively. Every symbol must have bar data for exactly (and all) the same dates, otherwise Wealth-Lab has to synchronize the data by adding or deleting bars of the secondary symbols.
Is it possible to pyramid in rotational strategies?Yes, see
this forum thread for a code example.
I need other rotation rule other than the built-in RSI.- To substitute the RSI indicator with another data series, modify this line:
holder.rsi = RSI.Series(Bars.Close, Period)bar;
- To modify the sorting order (i.e. keep ones with the highest RSI), do this:
// IS:
list.Sort(this);
// CHANGE TO:
list.Sort(this);
list.Reverse();
Optimization
Can't optimize a Strategy. What am I missing?Optimizer is not available for:
- Chart-only windows
- When using Streaming data
- If you've hidden the Strategy Window's Status bar:
To see the Optimize label in a Strategy Window, show the Status bar and turn off Streaming.
Optimization is slow and takes much time. Is it possible to speed up?- Reduce the number of runs required by:
- disabling unnecessary parameters (use parameter checkboxes, since version 6.9)
- make the parameter step wider
- load less historical data
- Choose a faster optimization method:
- Launch two (three...) WL instances with the same strategy in different Windows accounts (usernames). Use Win-L shortcut (multi-login) to switch between them.
- Copy your data and Strategy files to each user account's AppData... folder
- Change the CPU affinity for every running WL process to each CPU core
- Tweak the Strategy Parameters so that they don't overlap.
- A scripting solution for semi-automation of starting the WL instances with CPU affinity assignment may be possible with Windows script
- An alternative to multiple WL instances is to set up several virtual machines
Why Sharpe ratio is not provided in Optimization Results?Switch to one of the Portfolio Simulation options from the Position Sizing dialog. Before runnning an optimization, switch to a Scorecard with Sharpe ratio: Extended or MS123 Scorecard.
In Raw Profit mode, there is no starting capital by definition and consequently, no Sharpe, no Max Drawdown % or Exposure.
Position sizing
See
FAQ > Miscellaneous > Position sizingStrategy In General
Why is main (trading) loop required in live trading?Strategies are run bar-by-bar, always processing the most recent one and determining if an action is required. Actions that occurred on previous bars create Positions. In order to determine the current positions, you need to loop through previous bars to determine if the strategy had generated a trade, and now the current bar can be used to exit from it. Not having the main (trading) loop turns your strategy into a
scan because it no longer has "memory" required to keep the trade history.
How to start Buy&Hold from specific bar (not at bar #0)?The Wealth-Lab User Guide (
Strategy Window > Backtesting Strategies > Inside a Portfolio Simulation > Note on Lead Bars) explains why this is not a feature. Fortunately, there is a workaround: use
GetAllDataForSymbol method from Community Components library to create indicators that are valid from bar 0, and therefore can start the trading loop at bar 1.
What is optimal for my trading, Strategy Monitor or Strategy window?Please see this KB article:
Can't execute a Strategy - I run it but nothing comes up. What am I missing?When you make changes in the Editor, you must click the "Compile" button in the Editor toolbar, or click "Run the Strategy", which compiles and runs.
Why all my backtest trades are negative?You have applied a (very small) position size like 1 Share and haven't disabled the default commission plan in Wealth-Lab's Preferences.
Is there a way to make WL6 specify the line in the strategy where the error occurs?No. They're displayed for compilation errors, but not runtime errors. Strategies in Version 6 run from compiled code, so line numbers in the editor aren't known directly. If the contents of the error doesn't give you a good clue, you can use the
debug techniques.
Is there a way to reuse a function in Strategies? Is it possible to create a library of reusable functions?It's not possible to call a method from a Strategy saved in an XML file. You need to code your functions and methods in a .NET language of your choice, build a .NET assembly, and place it in Wealth-Lab's main directory under Program Files with the rest of dynamically linked libraries (DLLs). Then reference it in your Strategy by using References in the Editor and/or with a "using" directive.
Every time I run a Strategy I get a different result. What am I missing?Symptoms:
You're running a Strategy in Multi-Symbol Backtest mode (MSB) using Portfolio Simulation mode (in other words,
not Raw Profit) and every time it runs you get a different result. In addition, your entry has no position priority assigned.
Solution:
Solution: assign position priority. Everything is explained in the Wealth-Lab User Guide, so we are not going to duplicate its contents here. You're welcome to take a look in the Wealth-Lab User Guide,
Strategy Window > Backtesting Strategies > How Trades Are Chosen. Another resource is the QuickRef entry for
Position.Priority.
Additionally, enabling "Use Worst Trades in Portfolio Simulation" in Wealth-Lab's Preferences >
Backtest Settings presents an easy way to make the backtest non-random without touching the Strategy code.
Strategy runs slow.Symptoms:
It takes much time for a typical strategy to run, for example, making it impossible to work in the Strategy Monitor.
Solution:
- Check if you're requesting on-demand updates during market hours. Turn off on-demand updates.
- In Preferences, disable unneeded performance visualizers and reopen the Strategy window for the changes to apply.
- (Windows XP only) In case of unexplainable, partial slowdown of the application, reinstall .NET framework.
Out of memory problems.Symptoms:
Wealth-Lab generates an out-of-memory exception message when you try to perform a Multi-Symbol Backtest on a big amount of high frequency data (e.g. a big DataSet of 1-minute symbols, an ASCII file with long second-based history).
Reason:
By design, Wealth-Lab 6 requires the data to remain in memory to be available in PosSizer calculations (position sizing scripts) and visualize all Performance Visualizers.
Wealth-Lab 6 requires twice as much memory as WL4 because now double precision is used, taking 8 bytes in memory for each data element. You can realistically estimate memory consumption by using the following simple math:
Required RAM = Number of stocks * number of bars * number of data series (typically 6: DateTime + OHLCV) * 8 bytes
Solutions:
- Break up the Multi-Symbol Backtest. If you're trading 1-minute bars, it's unlikely that your time horizon is on the order of months and years.
- Turn off some extra Performance Visualizers (Preferences - Performance Visualizers - uncheck).
- Call Bars.Cache.Clear at the end of your strategy to explicitly clear the internal cache that stores DataSeries and free memory.
- Install the x64 version of Wealth-Lab Developer/Pro if your operating system supports it.
- Install more RAM for 64-bit Wealth-Lab to consume.
- Avoid performing multiple optimizations successively in the same window without closing and reopening the Strategy to force Windows do a memory cleanup.
- After days of always-on operation, it's best to completely restart Wealth-Lab before starting another memory-intensive optimization.
- If your Strategy code has grown large enough (like dozens of thousands lines), move it to a compiled library (DLL) using Visual Studio.
I want to test a strategy that buys and sells with stop/limit orders on the same bar.You can't realistically backtest with stop and limit orders on the same bar. What is reliably known is that the open occurred before all the other prices and that the close occurred the last. The intra-bar price dynamics is unknown.
To avoid inadvertent peeking into the future (and inflated backtest results) when dealing with stop/limit signals on the same bar, apply a workaround:
How to keep Strategy from executing when I drag a Strategy parameter slider?This convenient feature is by design and applies to single-symbol backtests only. Consequently, if you click on DataSet title to switch to multi-symbol mode before changing a parameter, the strategy will not re-execute.
Why am I unable to "Reset" and "Save parameters"Because the default setting of the parameter value(s) may have been altered by "Save Parameters". In this case, the saved setting overrides the default value in the Editor. To set a new default parameter value, change a slider and Save.
Alerts are not triggered.Symptoms:
You get a Buy/Sell signal but do not get an Alert.
Answer:
Here's a quick list of things to check:
- Is the buy/sell signal happening on bar? Alerts only work for bar+1.
- Are your strategy using AtClose orders? These are not going to produce an alert. Check out the WealthScript Programming Guide: Programming Trading Strategies > Alerts > How to: Alert for AtClose Signals.
- Does your main loop end prematurely - like this?
for(int bar = 20; bar < Bars.Count-1; bar++)
- In Portfolio Simulation mode, there may be not enough capital to execute a trade.
- Even if you're in Raw Profit mode, with "Fixed Dollar" selected trades can be skipped if the dollar size is less than the basis price of the instrument. It frequently happens when backtesting higher-priced indexes in RP mode. Example: Fixed Dollar = $5,000, Index price = 10,000, trade can't be taken (out of money).
- Preferences > Backtest settings > "Reduce quantity based on volume". Uncheck "Limit a Position's Quantity to a Percentage of the Bar's Volume".
- If using Strategy Monitor, make sure you've highlighted the Strategy and pressed the Activate Strategy button
- If Auto-Staging/Placing Alerts do not appear in the Orders tool, check that the account that you're trading has the offsetting position. By default, Portfolio Sync is enabled in Trading Preferences, and one of it's functions is to suppress orders for alerts that do not have a actual position.
How to display portfolio equity (exposure, drawdown etc.) series and/or interact dynamically with the portfolio level equity in Strategy?As the WealthScript Programming Guide suggests (
Programming Trading Strategies > Strategy Code Limitations), it's not possible to create trading strategies that enter or exit trades as a function of portfolio equity. The natural way is to use this PosSizer:
Trading the Equity Curve. However, workarounds exist on how to access the portfolio equity DataSeries in Strategies:
WealthScript
How do I start with C# ?If you want to learn programming, then you can take a C# class, buy a book, or use any number of the hundreds of free sources on the web. Typically, any beginner book picked from the bookshelf would do the job because you don't have to be a programmer to become proficient with WealthScript - like
"Microsoft C# Programming for the Absolute Beginner". To create strategies from scratch, you need to have the basic knowledge of such language concepts as: language syntax, data types, operators and statements, loops, classes, Date/Time and String classes.
If you're starting out, a very good, simple and comprehensible free e-book is
C# Yellow Book by Rob Miles (PDF, direct download link:
2019 edition, previous versions:
2014 ed.,
2015 ed.,
2016 ed.).
There are great many free .NET and C# resources on the web as well. Use a search phrase like
"Free online C Sharp Books" when googling, or here's just a handful assorted links:
Don't forget that
Microsoft Visual Studio 2019 Community edition and
SharpDevelop IDEs are free.
Finally, the WealthScript Guide and the QuickRef concentrate on giving concrete examples of programs that almost everyone is likely to write. After studying the basics of C#, working with examples is a great way to learn how to program.
I'm a Wealth-Lab 3/4 user, how to learn C# ?Both Delphi/Pascal and C# are modern object-oriented languages, so once you make this pretty easy transition to C#, you will never look back. Here are some
tips to help you along the way:
- Although there's some learning curve in gaining basic knowledge of what .NET has to offer to streamline your coding, WealthScript hasn't changed conceptually. For example, the "using" statements in C# are similar to $Includes. Another change worth mentioning is that some of the old functions now have gone for good because they're already available as a part of the Microsoft .NET framework (see An equivalent WealthScript function can't be found).
- Start by looking at the prepackaged strategies. Concentrate on the Execute() method, ignoring the other stuff at first.
- Use the WealthScript Translator tool to convert your Wealth-Lab 4 strategies to run in Wealth-Lab 6 (Direct download link). Compare the code with its WLD3/4 origin.
- Start using the Strategy Builder (aka New Strategy from Rules). Create a strategy, then use the "Open code in new window" function. Examining the code is very helpful.
- Keep WealthScript Programming Guide open: along with the QuickRef tool, it's your source for many examples of no-nonsense, illustrative code samples for real life tasks.
TrendlineValue can't be accessed.Symptoms:
In a Strategy that loops through DataSet symbols using SetContext, TrendlineValue is not working. If you click on the symbol with the trendline, TrendlineValue code is executed whereas when you click on another symbol to start the Strategy, TrendlineValue returns zero.
Answer:
By design, it's not possible to access a Trendline Value (TLV) for other symbols through SetContext since the TrendLine(s) don't exist in the current chart.
Workaround:
For a solution that makes possible accessing TLVs in an unsupported context (e.g. Strategy Monitor), see this KB article:
WealthScript Techniques: Trading with Trendlines in the Strategy Monitor.
How to reduce the number of decimal places for display/debug?Question:
Is it possible for values of type
double to have just two digits after the decimal? I don't need the full precision.
Answer:
There are at least two ways:
- Use the Bars.FormatValue method will formats the specified value into a string, using the current number of decimals.
- Or use a custom format string like this:
Closebar.ToString("0.00")
More on topic:
MSDN: Custom Numeric Format Strings
String Format for Double
Is there ChangeBar method in WL6?WL6 doesn't contain a ChangeBar lookalike, but it's easy to modify values of the Bars object:
protected override void Execute()
{
DateTime dt = new DateTime(2008,01,23);
for(int bar = 20; bar < Bars.Count; bar++)
{
//Datebar = dt;
Openbar = SMA.Series( Open, 20 )bar;
Highbar = SMA.Series( High, 20 )bar;
Lowbar = SMA.Series( Low, 20 )bar;
Closebar = SMA.Series( Close, 20 )bar;
}
}
Since the Date collection is read-only, it is not possible to change the bar's date. See what happens if you uncomment the Date[bar] = dt line.
I want to chart an indicator, but without the stock price. Can I hide the PricePane?Short answer: It's not possible to hide the PricePane
completely, but a workaround is available.
The chart is the primary data and neither it makes sense to remove it nor there is an associated WealthScript command to do it. Nonetheless, if you set the height of your ChartPane to the maximum possible value - that is
Int32.MaxValue - it will make the PricePane shrink to hairwidth:
protected override void Execute()
{
HideVolume();
ChartPane GiantPane = CreatePane(Int32.MaxValue,false,false);
PlotSeries( GiantPane, RSI.Series( Close,14 ), Color.Blue, LineStyle.Solid, 2 );
}
How to program MetaStock's PREV function in Wealth-Lab?There is a function in MetaStock formula language called
PREV that slows down processing dramatically, but is quite helpful.
A common mistake when translating a MetaStock formula with PREV statement is confusing it with the series value on the previous bar. However, MetaStock
does have a way to reference previous bar value which is "Ref": e.g. "Ref(c,-1)". PREV is a
statement-oriented self-referencing directive that references its own value on the previous bar.
If a bar loop is being used, simply reference the variable like shown below to create a PREV equivalent:
protected override void Execute()
{
for(int bar = 20; bar < Bars.Count; bar++)
{
/* In MetaStock:
a11:= (a10+PREV*(a5-1))/a5;
*/
a11 = ( a10+a11*( a5-1 ) )/ a5;
}
}
How do I code a rule for time of the day?Use the
Hour⁄Minute properties of the standard .NET
DateTime structure. Here's a helpful wrapper function that makes coding a little more straightforward:
How do I code a time-based exit?See:
Sell after X days.
How to code and plot relative strength ratios?Use
GetExternalSymbol. Examples:
Is there a way to see the trades on secondary symbols?Yes. To enter trades on secondary symbols, use the
SetContext method call. To visualize the trade arrows on a secondary symbol pane, you can plot them artificially - here's an illustration:
protected override void Execute()
{
int bar = Bars.Count-1;
var pane = CreatePane(30,true,true);
string UpArrowGreen = Convert.ToChar(0xe9).ToString();
string UpTriangleGreen = Convert.ToChar('\u25b2').ToString();
AnnotateBar( UpArrowGreen, bar, true, Color.Green, Color.Transparent, new Font( "Wingdings", 10, FontStyle.Bold ) );
AnnotateBar( UpTriangleGreen, bar-1, true, Color.Green, Color.Transparent, new Font( "Times New Roman", 10, FontStyle.Bold ) );
AnnotateChart( pane, UpArrowGreen, bar, 10, Color.Green, Color.Transparent, new Font( "Wingdings", 10, FontStyle.Bold ) );
AnnotateChart( pane, UpTriangleGreen, bar-1, 100, Color.Green, Color.Transparent, new Font( "Wingdings", 10, FontStyle.Bold ) );
}
Is there a workaround for Market on Close orders?Auto-trading MOC orders with Fidelity is impossible. As a workaround, you can use a market order on the 15:59 bar using the logic outlined in the WealthScript Programming Guide: Programming Trading Strategies > Alerts >
How to: Alert for AtClose Signals.
Is there a way to detect within my Strategy if it is executed in Multi-Symbol Backtest mode?Yes, it used to work in v6.6 and before. You can find the necessary code
here. Starting from v6.7 and newer, this technique no longer works.
Is it possible to tell in a Strategy if it is executed in Raw Profit mode or in Portfolio Simulation mode?Yes. Install the
Community Components library from our site and then use this function in your Strategy:
IsRawProfitMode.
I'm trying to divide two numbers and the result is zero.Symptoms:
You're trying to divide two apparently
double numbers and get 0 e.g.
double d = 123 / 456;
Answer:
In C#, this is considered to be an integer division i.e. "123" and/or "456" are
integer numbers, therefore you get 0.
You have to perform an implicit cast to
double or specify the divisor as a
double. Examples:
double d1 = 123 / 456d;
double d2 = 123 / (double)456;
double d3 = 123 / 456.0;
PrintDebug(d1 , d2 , d3 );
Can I detect divergences using Wealth-Lab?Sure. First, there's a built-in indicator:
Divergence. Next, there are existing strategies illustrating various techniques of divergence detection:
Leader of the MACD,
Asymmetric RSI,
Smooted RSI Inverse Fisher. Finally, we've got a
DivergencePlotter routine helping to detect and plot divergences between two DataSeries.
Is there a way to read/write values to an open Excel sheet?Yes, basically there are two approaches:
1. Using COM wrapper:
Prerequisite: install
Visual Studio Tools for Office.
2. Read and write Excel sheet names and cell values using database technology:
Note: To work with XLSX files, installing Microsoft Access Database Engine 2007/2010 redistributable is a prerequisite - just as it is when working with both XLS or XLSX files on 64-bit Windows. Moreover you need to adjust the connection string respectively.