WealthScript Techniques | Setups, Triggers, Delays, and Timeouts

Modified on 2017/08/31 09:36 by Administrator — Categorized as: Knowledge Base

Tutorial: Setups, Triggers, Delays, and Timeouts


If you can express a trading system in words, then you can almost certainly program it with WealthScript. Unlike most other analytical trading tools, WealthScript doesn't hide the trading system loop from the programmer and largely for this reason you can design systems in Wealth-Lab that could not even be realized on other platforms.

The programming power of WealthScript can overwhelm at first, and we tend to see the same questions when it comes to adding rather simple new methods or conditions to a Strategy. One favorite is adding delay after one event occurs (setup), before triggering some other action; and additionally storing a setup condition for a specific number of bars after which time it is no longer valid (timeout).

As in all true programming languages, there are many way to achieve the same result, and one of the solutions is invariably to declare a few new variables for keeping track of each condition. We'll explain how this is done, but first it's important to understand the difference between a setup and a trigger.


We'll define a trigger as the final condition or event required to make a trading decision. Typically, but not necessarily, a trigger is an isolated event such as the instant that an indicator crosses another having a longer period.

Examples of trigger functions:
See CrossOver, CrossUnder, CrossOverValue, CrossUnderValue, TurnUp, TurnDown in the QuickRef.

It's best to be precise when expressing trading system rules so that unexpected results do not occur. For example, if you want to buy stock when two indicators cross, don't test if one simply has a greater value than the other, test for the instant of crossover using one of the WealthScript functions.

Additionally, all AtStop and AtLimit trading signals (e.g., BuyAtStop, ShortAtLimit, etc.) serve as triggers by themselves. For these, you pass a stop/limit price as a parameter and when the actual price reaches or crosses this price, the function is triggered at the stop/limit price immediately.

Almost invariably, AtMarket (and frequently AtLimit and AtStop) orders are preluded by triggers. Nonetheless, triggers are often preceded by setups.


A setup is a condition, or series of conditions, required to enable a trigger. Setups are typically, but not necessarily, conditions with duration lasting more than 1 bar. An example of a setup is, "if Price > the 50-day SMA then {do something}." Commonly, setups are a result of a logical combination (AND: &, &&, OR: |, ||) of more than one condition.

    Setup operators:  ==, >, >=, <, <=

In the code fragment below, the setup requires that today's Close be above the 50-day SMA and that volume be greater than or equal to its 20-day SMA before allowing the trigger a chance to buy tomorrow when price crosses today's closing price.

  // Enable the stop order (trigger) with a setup
  if( Close[bar] > SMA.Series( Close, 50 )[bar] )
    if( Volume[bar] >= SMA.Series( Volume, 20 )[bar] )
      BuyAtStop( bar + 1, Close[bar] );

Aside: Note that stacking if/then statements (as shown above) is logically equivalent to using the AND (&&) operator. The fragment below is identical in speed and function to the one above, i.e., WealthScript short-circuits logical expressions such that subsequent conditions are tested only if the preceding condition is 'true'.

  // Enable the stop order (trigger) with a setup
  if(( Close[bar] > SMA.Series( Close, 50 )[bar] ) && ( Volume[bar] > SMA( Volume, 20 )[bar] ))
    BuyAtStop( bar + 1, Close[bar] );

Setups and Triggers in the Rule-Based Strategy Wizard

In reality, setups and triggers are subcategories of a large group of conditions. When using Rule-Based Strategies, you need not think about which condition is a setup and which is a trigger. Rather, you will naturally choose a trigger as the final condition for a trading action. You'll automatically stack and combine other conditions to serve at setups. However, the reason we mention the difference here is so that you can treat each independently when manually coding delays and timeouts.

Adding Delays and Timeouts

Let's start with a couple more definitions:

Delay: A period of time, or number of bars, during which an action is to be inhibited.
Timeout: A period of time during which an action is enabled, but after which time the action is inhibited.

In other words, a delay is the opposite of a timeout, and we can implement them in a similar manner in a script by negation, using the NOT (!, != ) operator. Consequently, setups can be an enabling condition, or conversely, an inhibiting condition.

Here's a typical, straightforward method to implement a delay or timeout for a condition. (Keep in mind that there are always a number of ways to accomplish the same thing in programming.)

  1. Declare a boolean variable to store the state of the condition and an integer variable to hold the BarNumber when the condition initially tests true.
  2. If the boolean is false, test the setup condition. If the condition is true, set the boolean true and assign the current BarNumber to the integer.
  3. Test the boolean again, and if true, test the trigger condition.
  4. Reset the boolean to false if Bar + 1 - BarNumber exceeds the time out period.


When my setup is valid, how can I enter an order at the same limit price for 3 consecutive bars?

Let's demonstrate with a simple setup condition: Volume of the current bar is greater than twice the 10-period SMA of Volume. We declare a variable to store the bar number on which the setup occurred (SetupBar) and another to keep track of the current state of the setup (SetupValid).

Since the setup with be valid for 3 bars, it's necessary only to check the setup condition if SetupValid is false. When the setup is detected, we set SetupValid to true and store the Bar number. Thereafter, it's a simple matter to check the trigger condition only if the setup is valid. Finally, if either the trade is filled or the setup times out, we set SetupValid to false and the process repeats.

Example Use

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

namespace WealthLab.Strategies { public class SetupDemo : WealthScript { protected override void Execute() { // Example of a setup with a 3-bar timeout int SETUP_TIMEOUT = 3; int SetupBar = 0; bool SetupValid = false; double MyLimit = 0; SMA volSma = SMA.Series( Volume,10 ); PlotSeries( VolumePane, volSma, Color.Teal, LineStyle.Solid, 2 ); PlotStops();

for(int bar = 20; bar < Bars.Count; bar++) { if (IsLastPositionActive) { Position p = LastPosition; if( !SellAtStop( bar+1, p, p.EntryPrice * 0.95 ) ) SellAtLimit( bar+1, p, p.EntryPrice * 1.10 ); } else //if (!IsLastPositionActive) { // When a position is not active, test for the Setup if not already valid if( !SetupValid ) { if( Volume[bar] > 2 * volSma[bar] ) { SetupValid = true; SetupBar = bar; MyLimit = Close[bar] - 0.5 * ATR.Series( Bars, 5 )[bar]; } }

if( SetupValid ) { // if the order is filled set SetupValid to false if( BuyAtLimit( bar + 1, MyLimit ) != null ) SetupValid = false; else // reset if Setup has timed out SetupValid = bar + 1 - SetupBar < SETUP_TIMEOUT;

// Color the VolumePane to indicate that the setup was valid this bar SetPaneBackgroundColor( VolumePane, bar, Color.FromArgb( 30, Color.Green ) ); } } } } } }