Wealth-Lab Wiki

API ChartStyles Community Components Community Indicators IndexDefinitions Knowledge Base Misc Optimizers Pending Deletion PosSizers Providers Standard Indicators TASC Traders Tips TASCIndicators Tutorial Videos Visualizers
RSS

Navigation


Quick Search
»
Advanced Search »


Introductory | Bars, Loops, and Bar + 1

RSS

Bars, Loops, and Bar + 1

Original article by Robert Sucher in the legacy Knowledge Base here.

Wealth-Lab Developer has features such as order slippage and variable commissions to bring trading simulation as close to reality as possible. Likewise, your task as a trading system designer is to express your system in C# code that validly recreates security orders as they would have been and will be executed in real life.

Bar Definition

A bar is any interval of time that has an open, high, low, and closing price, whose values may be different or equivalent. These can consist of any number of minutes (e.g., 1, 2, 5, 20, 30-minute bars), 1 day, 1 week, or 1 month. Wealth-Lab 6 also includes support for bars that are multiples of ticks or seconds. At the time of this writing, it does not provide a native scaling ability for multiples of daily, weekly, monthly, quarterly, or yearly time frames.

Note that each bar has its own properties, which include Date, OHLC/V, Time (for intraday) and OI values (if available for futures). The values of the "raw" Primary Series can be retrieved using the WealthScript functions in the Data Access and Date/Time categories. Technical analysis of stocks and futures generally involves manipulating these Primary Series to create indicators that have some statistical significance in the prediction of future price. See the WealthScript Programming Guide, "Data Series" for more information.

Bar as a Variable

In Wealth-Lab V5 (.NET), WealthScript variable-naming rules are the same as in C#.

With the liberty you have for naming variables, it's possible to assign variables names with meaning to give your code readability. The variable name bar is an example of a well-named variable. bar has become the standard variable name used as the main loop index variable by WealthScript programmers like yourself. This code fragment shows how to cycle through each bar in the chart starting with Bar Number 20.


for(int bar = 20; bar < Bars.Count; bar++)
{
	// do something with the variable bar }
	if( bar == 100 )
		DrawLabel( PricePane, "We hit bar " + bar.ToString() );
}

You could just as easily use the names b, xyz, or RightNow in place of Bar, but none would be as meaningful.



Bar as a Loop Index Variable

As shown in the fragment above, bar is most typically used as the index variable in a for loop. This means that with each iteration of the loop, the value of bar will be incremented by 1. The first time the loop executes the statements between the curly braces, bar will have the value 20. With the next iteration, bar will be 21, and so on until bar reaches the value given by Bars.Count - 1 , which is equivalent to the Bar Number of the final bar loaded in the chart. (The WealthScript property Bars.Count returns the total number of bars in the chart. Since first bar of the chart is Bar Number 0, Bars.Count - 1 represents the last bar.)

This loop processes each bar in the chart (in this case beginning with Bar Number 20), indexed one at a time. Note that bar does not have units of the time interval, rather it is only an index. Consequently, you can use the same loop for any DataSet regardless of its interval. However, if your script uses other WealthScript functions that apply only to Daily or Intraday bars, for example, the script will function properly only on DataSources of the appropriate interval.

... hold your horses! Why does the loop start at 20?

Strategies typically contain one or both of the following types of loops: indicator-creation loops and the main trading loop. Here, we're concerned with the latter type. Briefly, the main trading loop should start when all indicators utilized are valid and stable. For example, if you use both a 10-period and 20-period moving averages, you should start your trading loop no earlier than the 20th bar, which is the period of the longest average. Due to their nature, other popular indicators, such as RSI, take longer than the specified period to stabilize, and therefore the starting bar should be adjusted accordingly to achieve predictable results. Check the WealthScript Programming Guide for more on Stability of Indicators.

Using bar + 1

While creating indicators or processing trades in the main loop, you must be careful to use data only from the current Bar or previous/historic bars on which to base your trading signals. Though more subtle forms of "peeking" exist in WealthScript, probably the most common is to execute a trade at the opening price (market order) or during a bar (limit or stop) as a result of an indicator whose value was calculated based on the same bar's high, low, or closing price. This type of trade is impossible to realize in real-life and will almost certainly lead to inflated results and misplaced confidence in a trading system.

To demonstrate this classic mistake to yourself, run the following correctly-written script. It detects if the moving averages CrossOver or CrossUnder on the current bar , and if true, it buys or sells at market on the next bar, i.e. bar + 1 . Recall that bars can be minutes, days, weeks, etc.

Depending on your data set, it's most likely that you'll find this to be a losing system.


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

namespace WealthLab.Strategies { public class MyStrategy : WealthScript { protected override void Execute() { SMA hSMA1 = SMA.Series( Close, 10 ); SMA hSMA2 = SMA.Series( Close, 20 ); PlotSeries( PricePane, hSMA1, Color.Blue, LineStyle.Solid, 1 ); PlotSeries( PricePane, hSMA2, Color.Red, LineStyle.Solid, 1 );

for(int bar = 20; bar < Bars.Count; bar++) { if (!IsLastPositionActive) { if( CrossOver( bar, hSMA1, hSMA2 ) ) BuyAtMarket( bar+1 ); } else { Position p = LastPosition; if( CrossUnder( bar, hSMA1, hSMA2 ) ) SellAtMarket( bar+1, p ); } } } } }

Now re-run the system after removing the ′+1′ from the trading signals and notice the rather great improvement in performance when using the same data set. The difference is in the ability to know the value of two moving averages at the end of the day, but making a trading decision on the market open based on that future knowledge - in a word, peeking. As demonstrated in the WealthScript code above, the way to avoid this type of error is to pass bar + 1 to the trading signals: Buy*, Short*, Sell*, and Cover*; where * can be AtMarket, AtLimit, AtStop, or AtClose. (AtClose orders are actually an exception to this rule, but use of this signal type has other trading implications.)

Note that passing bar + 1 to other functions will cause a List index out of bounds error when the trading loop reaches the last bar in the chart. This indicates that you are trying to access data that does not yet exist, consequently your system is likely peeking and the situation must be corrected.

Though this discussion should be enough to convince you to use bar + 1 in trading signals (exceptions may exist), there's another important reason to do so - to create Alerts.

Alert Generation

Alerts are trading signals, or orders, that should be placed on the following bar. For example, when trading daily bars, you would run your Strategy each evening after the close of the day. If the script generates an Alert, you would place a corresponding order the next day. On the other hand, when trading intraday, you must place the order immediately after receiving an Alert.

When coding a trading system in WealthScript the only requirement to generate an Alert is to pass bar + 1 to one of the trading signals as outlined above, so that the trading signal occurs on a bar beyond the last bar in the Chart, given by Bars.Count - 1. Consequently, during the final iteration of the trading loop, when bar is assigned the value Bars.Count - 1, a trading signal such as BuyAtMarket( bar + 1 ); will create an alert since the Bar Number passed to the signal is greater than Bars.Count - 1.

Alerts triggered by Wealth-Lab tools can be routed to the Orders tool for automated processing, or, you can enter orders manually while monitoring Wealth-Lab for new signals.

Tip: if you're looking for a workaround to get alerts in a system working with AtClose orders, see the WealthScript Programming Guide: Programming Trading Strategies > Alerts > How to: Alert for AtClose Signals.

Summary

This image provides a summary of what we've learned thus far.

Image

Conclusion

The following concept have been outlined:

  • A bar can be made up of OHLC/V data from multiples any time frame - ticks, seconds, minutes, 1 day, 1 week, or 1 month.
  • bar is a loop index variable that refers to the current bar being processed.
  • bar + 1 refers to the bar that follows the one currently being processed. It could be the next day, the next week, etc. based on the scale of your DataSource.
  • Generally speaking, you should pass bar + 1 to trading signals (only) to avoid peeking and to enable Wealth-Lab to generate trading Alerts.

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.

Used under license from FMR Corp. Copyright 2008 FMR Corp. All rights reserved.


ScrewTurn Wiki. Some of the icons created by FamFamFam.