Writing Strategies

In Tradesignal, many strategies are available, either delivered with the software or offered for download from the website.

However, wishes may remain unfulfilled or you may have new ideas that need to be tested. You can always use the Trading Strategy Wizard to design a new strategy. You can also program new strategies (or edit available ones) in Tradesignal by using the Equilla language.

In the following you will find an example showing how to write a strategy using Equilla. It is only intended to give you a basic introduction. For details on Equilla, please refer to articles in the Equilla Basics category.

Programming a Bollinger Band - RSI System


Writing a new strategy
The strategy calculates the Relative Strength Index for an instrument. Based on these values, Bollinger Bands are then constructed. The crossings between the RSI and the Bollinger Bands are used as trading signals. In addition, Stop Loss and Trailing Stop are calculated. The idea behind this setup is to substitute the static extremes of the Relative Strength Index with more flexible zones that adapt to the movements of the indicator.

Creating the Strategy

  1. In the toolbox, click on the Strategies button.
  2. In the Related Tasks area, select New Strategy.
  3. In the next dialog, select the option Use the Equilla Formula Language to write the strategy.
  4. Select a folder, e.g. "Tradesignal Files".
  5. Type the name "Bollinger-RSI-Bands".
  6. Click on Done.
Now you can enter the source code of the strategy in the Equilla Editor. The areas are described in the following sections. The complete code can be found at the end of this article.

Entering the Header

In the header area, the input parameters of the used indicators and necessary variables are declared. In addition, we enter the meta information for the subchart creation.

//Creating a subchart
Meta:
    SubChart( true );

//Defining the input parameters for the indicators
Inputs:
    PeriodAvg( 20 , 1 ),
    PeriodStd( 10 , 1 ),
    FactorStd( 2.0 , 0.0 ),
    PeriodRSI( 14 , 1 ),
    PeriodATR( 10, 1 ),
    FactorAtr( 1.5, 0.0 ),
    PeriodTrail( 20 , 1 ),
    TradeMode( outsideIn, insideOut );


//Declaring the variables that we need for storing calculation results
Variables:
    avgValue, upperBand, lowerBand, rsiValue, stdValue, atrValue,
    stopValue, trailValue, activeStop;

Programming the Calculations for the Indicators and Stops

In this part, the indicator calculations are entered. For most of them, we will use available Equilla Functions. However, a new calculation is written for the Bollinger Bands, as we want to use the RSI as their basis.

//Calculating the RSI
rsiValue = RSI( Close, PeriodRSI );
//Calculating the Bollinger Bands constituents (based on the RSI)
avgValue = Average( rsiValue, PeriodAvg );
stdValue = StdDeviation( rsiValue, PeriodStd );
//The upper band is calculated with the average and the added standard deviation
upperBand = avgValue + ( FactorStd * stdValue );
//The lower band is calculated with the average and the subtracted standard deviation
lowerBand = avgValue - ( FactorStd * stdValue );

//Calculating the Average True Range for the Stop Loss
atrValue = Average( TrueRange, PeriodAtr );
//Calculation the Average as Trailing Stop
trailValue = XAverage( Close, PeriodTrail );

Defining Trading Conditions and Programming Order Generation

In this part, the conditions for trading signals are defined and the orders are generated. Two modes are defined:
  • The mode outsideIn is designed so that the RSI has to cut the Bollinger Bands from outside in for signal generation. This mode is preferable for correction movements.
  • The mode insideOut is designed so that the RSI has to cut the Bollinger Bands from inside out, i.e. in trend direction. This mode is optimal for strong trends.
//Setting the trading conditions
//Signals are generated when the RSI crosses the bands from outside in
If TradeMode = 0 Then
    Begin
        //Sale when the RSI crosses the lower band from outside in.
        If rsiValue crosses over lowerBand Then
            Begin
                Buy("LongIn") Next Bar at Market;
                //Calculating the price for the Stop Loss
                stopValue = Close - ( FactorAtr * atrValue );
            End;

        //Short sale when the RSI crosses the upper band from outside in.
        If rsiValue crosses under upperBand Then
            Begin
                Short("ShortIn") Next Bar at Market;
                //Calculating the price for the Stop Loss
                stopValue = Close + ( FactorAtr * atrValue );
            End;
    End
Else
    //Signals are generated when the RSI crosses the bands from inside out
    Begin
        //Sale when the RSI crosses the lower band from inside out.
        If rsiValue crosses over upperBand Then
            Begin
                Buy("LongOut") Next Bar at Market;
                //Calculating the price for the Stop Loss
                stopValue = Close - ( FactorAtr * atrValue );
            End;
        //Short sale when the RSI crosses the upper band from inside out.
        If rsiValue crosses under lowerBand Then
            Begin
                Short("ShortOut") Next Bar at Market;
                //Calculating the price for the Stop Loss
                stopValue = Close + ( FactorAtr * atrValue );
            End;
    End;

Handling of the Stop Loss Prices

For the Stop Loss, the Average True Range (ATR) is calculated. The value for the initial stop results from the ATR multiplied with a factor. As Trailing Stop, the Exponential Moving Average based on the instrument is calculated. If the price cuts this average inverse to the trade, the trade is closed. The program uses both stop values and compares which one is better positioned and more protective of the trade. That value is finally output as a stop order for the next trading period.

/* Here the handling of stop values is done: For long positions: The stop loss is valid as long as the trailing stop is below it. For short positions: The stop loss is valid as long as the trailing stop is above it. */

//Recognizing long positions
If MarketPosition = MarketPositionLong Then
    Begin
        //If the stop loss is better positioned than the trailing stop
        //the stop loss is set
        If ( stopValue > trailValue ) Then
            Sell("Stop Loss") Next Bar at stopValue Stop;
        //If the trailing stop is better positioned than the stop loss
        //the trailing stop is set
        If ( trailValue > stopValue ) And ( trailValue < Close ) Then
            Sell("Trail") Next Bar at trailValue Stop;
    End;

//Recognizing short positions
If MarketPosition = MarketPositionShort Then
    Begin
        //If the stop loss is better positioned than the trailing stop
        //the stop loss is set
        If ( stopValue < trailValue ) Then
            Cover("Stop Loss") Next Bar at stopValue Stop;
        //If the trailing stop is better positioned than the stop loss
        //the trailing stop is set
        If ( trailValue < stopValue ) And ( trailValue > Close ) Then
            Cover("Trail") Next Bar at trailValue Stop;
    End;

Displaying the Indicators in Subcharts

This is the easiest part. Only the indicators that are used for signal generation are displayed here.

//Graphic display of indicators
DrawLine( rsiValue, "RSI", StyleSolid, 1, blue );
DrawLIne( upperBand, "Upper Band", StyleSolid, 1, darkGreen );
DrawLIne( lowerBand, "Lower Band", StyleSolid, 1, red );

Applying the Strategy

Compile the code either by pressing F7 or by clicking on the button Compile Script in the Equilla Editor group. The code is checked for errors, saved and then available in the list of strategies in the toolbox by the name "Bollinger-RSI-Bands".

You can now apply it to a chart it as described in Using Strategies, for example with drag and drop.

The Complete Code

//Creating a subchart
Meta:
    SubChart( true );

//Defining the input parameters for the indicators
Inputs:
    PeriodAvg( 20 , 1 ),
    PeriodStd( 10 , 1 ),
    FactorStd( 2.0 , 0.0 ),
    PeriodRSI( 14 , 1 ),
    PeriodATR( 10, 1 ),
    FactorAtr( 1.5, 0.0 ),
    PeriodTrail( 20 , 1 ),
    TradeMode( outsideIn, insideOut );


//Declaring the variables that we need for storing calculation results
Variables:
    avgValue, upperBand, lowerBand, rsiValue, stdValue, atrValue,
    stopValue, trailValue, activeStop;


//Calculating the RSI
rsiValue = RSI( Close, PeriodRSI );
//Calculating the Bollinger Bands constituents (based on the RSI)
avgValue = Average( rsiValue, PeriodAvg );
stdValue = StdDeviation( rsiValue, PeriodStd );
//The upper band is calculated with the average and the added standard deviation
upperBand = avgValue + ( FactorStd * stdValue );
//The lower band is calculated with the average and the subtracted standard deviation
lowerBand = avgValue - ( FactorStd * stdValue );

//Calculating the Average True Range for the Stop Loss
atrValue = Average( TrueRange, PeriodAtr );
//Calculation the Average as Trailing Stop
trailValue = XAverage( Close, PeriodTrail );

//Setting the trading conditions
//Signals are generated when RSI crosses the bands from outside in
If TradeMode = 0 Then
    Begin
        //Sale when the RSI crosses the lower band from outside in.
        If rsiValue crosses over lowerBand Then
            Begin
                Buy("LongIn") Next Bar at Market;
                //Calculating the price for the Stop Loss
                stopValue = Close - ( FactorAtr * atrValue );
            End;

        //Short sale when the RSI crosses the upper band from outside in.
        If rsiValue crosses under upperBand Then
            Begin
                Short("ShortIn") Next Bar at Market;
                //Calculating the price for the Stop Loss
                stopValue = Close + ( FactorAtr * atrValue );
            End;
    End
Else
    //Signals are generated when RSI crosses the bands from inside out
Begin
        //Sale when the RSI crosses the upper band from inside out.
        If rsiValue crosses over upperBand Then
            Begin
                Buy("LongOut") Next Bar at Market;
                //Calculating the price for the Stop Loss
                stopValue = Close - ( FactorAtr * atrValue );
            End;
        //Short sale when the RSI crosses the lower band from inside out.
        If rsiValue crosses under lowerBand Then
            Begin
                Short("ShortOut") Next Bar at Market;
                //Calculating the price for the Stop Loss
                stopValue = Close + ( FactorAtr * atrValue );
            End;
    End;

/* Here the handling of stop values is done: For long positions: The stop loss is valid as long as the trailing stop is below it. For short positions: The stop loss is valid as long as the trailing stop is above it. */

//Recognizing long positions
If MarketPosition = MarketPositionLong Then
    Begin
        //If the stop loss is better positioned than the trailing stop
        //the stop loss is set
        If ( stopValue > trailValue ) Then
            Sell("Stop Loss") Next Bar at stopValue Stop;
        //If the trailing stop is better positioned than the stop loss
        //the trailing stop is set
        If ( trailValue > stopValue ) And ( trailValue < Close ) Then
            Sell("Trail") Next Bar at trailValue Stop;
    End;

//Recognizing short positions
If MarketPosition = MarketPositionShort Then
    Begin
        //If the stop loss is better positioned than the trailing stop
        //the stop loss is set
        If ( stopValue < trailValue ) Then
            Cover("Stop Loss") Next Bar at stopValue Stop;
        //If the trailing stop is better positioned than the stop loss
        //the trailing stop is set
        If ( trailValue < stopValue ) And ( trailValue > Close ) Then
            Cover("Trail") Next Bar at trailValue Stop;
    End;

//Graphic display of indicators
DrawLine( rsiValue, "RSI", StyleSolid, 1, blue );
DrawLIne( upperBand, "Upper Band", StyleSolid, 1, darkGreen );
DrawLIne( lowerBand, "Lower Band", StyleSolid, 1, red );