Trading

The Trading category contains methods used to enter and exit long and short Positions.

BuyAtMarket

AutoProfitLevel Property

double AutoProfitLevel

Specifies the initial profit target level for the next Position to be created. The value, analogous to RiskStopLevel, is the price at which the same-bar Limit order should be placed. It is valid for any BarScale.

Remarks


Example

protected override void Execute(){
PlotStops();
    int bcm1 = Bars.Count - 1;
    DataSeries sma1 = SMA.Series(Close, 8);
    DataSeries sma2 = SMA.Series(Close, 20);
    PlotSeries(PricePane, sma1, Color.Green, LineStyle.Solid, 1);
    PlotSeries(PricePane, sma2, Color.Red, LineStyle.Solid, 1);

    for(int bar = Bars.FirstActualBar + 20; bar < Bars.Count; bar++)
    {
        if (IsLastPositionActive)
        {
            Position p = LastPosition;
            SellAtLimit( bar+1, p, p.AutoProfitLevel * 1.01 );
        }
        else if ( CrossOver(bar, sma1, sma2) )
        {
            AutoProfitLevel = Bars.High[bar];
            // also use same-bar exit for backtesting
            if (BuyAtMarket( bar+1 ) != null && bar < bcm1) 
                SellAtLimit( bar + 1, LastPosition, LastPosition.AutoProfitLevel, "same-bar exit" ); 
        }
    }
}
BuyAtMarket

BuyAtClose

Position BuyAtClose(int bar, string signalName);
Position BuyAtClose(int bar);

Buys a new long position at the specified bar, using the closing price of the bar as the entry price.  The position size will be calculated based on the closing price of the previous bar.  Returns a new Position object that represents the newly established position.

Remarks


Example

protected override void Execute(){
    for(int bar = 3; bar < Bars.Count; bar++)
    {
        if (!IsLastPositionActive)
        {
            // Three consecutive lower closes
            if( ( Bars.Close[bar] < Bars.Close[bar-1] ) &
                ( Bars.Close[bar-1] < Bars.Close[bar-2] ) &
                ( Bars.Close[bar-2] < Bars.Close[bar-3] ) )  
                BuyAtClose( bar );
        }
        if (IsLastPositionActive)
        {
            SellAtMarket( bar+1, LastPosition );
        }
    }
}
BuyAtMarket

BuyAtLimit

Position BuyAtLimit(int bar, double limitPrice, string signalName);
Position BuyAtLimit(int bar, double limitPrice);

Buys a new long position at the specified bar, using a limit order at the specified limitPrice.  The position size will be calculated based on the limitPrice.  If the price of the bar reaches the limitPrice or lower, BuyAtLimit returns a new Position object that represents the newly established position.  If the limitPrice was not reached, BuyAtLimit returns null.

Remarks


Example

protected override void Execute(){
    for(int bar = 20; bar < Bars.Count; bar++)
    {
        if (IsLastPositionActive)
        {
            //code your exit rules here
        }
        else
        {
            // Buy at limit at last bar's high minus 1.5 * 5-period ATR
            BuyAtLimit( bar+1, High[bar]-1.5*ATR.Series( Bars, 5 )[bar] );
        }
    }
}
BuyAtMarket

BuyAtMarket

Position BuyAtMarket(int bar, string signalName);
Position BuyAtMarket(int bar);

Buys a new long position at the specified bar, using the open price of the bar as the entry price.  The position size will be calculated based on the closing price of the previous bar. 

Remarks

  • Slippage, when activated, can affect the trade's execution price.
  • The optional signalName parameter will appear in the Strategy window trade list report.

Example

protected override void Execute(){
    // Open long position on the following bar based on this bar's indicator values
    DataSeries sma = SMA.Series( Close, 20 );
    for(int bar = 20; bar < Bars.Count; bar++)
    {
        if (IsLastPositionActive)
        {
            // Exit trade after 5 days
            if ( bar+1 - LastPosition.EntryBar >= 5 )
            SellAtMarket( bar+1, LastPosition, "Time-Based" );
        }
        else
        {
            // Buy at market next bar when the recent closing price crosses over the 20-period SMA
            if ( CrossOver( bar, Close, sma ) )
                BuyAtMarket( bar+1, "SMA CrossOver" );
        }
    }
}
BuyAtMarket

BuyAtStop

Position BuyAtStop(int bar, double stopPrice, string signalName);
Position BuyAtStop(int bar, double stopPrice);

Buys a new long position at the specified bar, using a stop order at the specified stopPrice.  The position size will be calculated based on the stopPrice.  If the price of the bar reaches the stopPrice or higher, BuyAtStop returns a new Position object that represents the newly established position.  If the stopPrice was not reached, BuyAtStop returns null.

Remarks

  • Slippage, when activated, can affect the trade's execution price.
  • If the market open above the stopPrice, the entry price of the position will be set to the market open price of the bar.
  • The optional signalName parameter will appear in the Strategy window trade list report.

Example

protected override void Execute(){
    DataSeries peak = Highest.Series( High, 20 );
    for(int bar = 20; bar < Bars.Count; bar++)
    {
        if (IsLastPositionActive)
        {
            //code your exit rules here
            //...
        }
        else
        {
            // Enter when the 20-period high is touched
            BuyAtStop( bar+1, peak[bar], "Breakout" );
        }
    }
}
BuyAtMarket

CoverAtAutoTrailingStop

bool CoverAtAutoTrailingStop(int bar, Position pos, double triggerPct, double profitReversalPct, string signalName);
bool CoverAtAutoTrailingStop(int bar, Position pos, double triggerPct, double profitReversalPct);

Covers the short Position specified in the pos parameter at the specified bar, using a trailing stop order.  The trailing stop is initiated only after the position reaches the profit level specified in the triggerPct parameter. The stop price is calculated based on the profitReversalPct parameter.  This value indicates the percentage reversal in the Position's profit that should be used as a stop level.

For example, assume we specify 30 for profitReversalPct, and our short Position had an entry price of $12 and is currently at $10 (a 20% profit so far).

The total profit so far is $12 - $10 = $2

30% of $2 is $0.60

The stop order will be placed at $10 + $0.60 = $10.60

The trailing stop price is maintained with the Position, and it is modified only when the calculated stop price is below the current trailing stop price.  CoverAtAutoTrailingStop returns a bool value indicating whether the price hit the current trailing stop level or above, and the Position was covered.  CoverAtAutoTrailingStop will also return false if the bar specified is greater than the number of bars on the chart.  In this case, a cover Alert will be generated instead.

Remarks

  • Slippage, when activated, can affect a trade's execution price.
  • If the market open above the current trailing stop price, the position will be covered at the market open price of the bar.
  • The optional signalName parameter will appear in the Strategy window trade list report.
  • To cover all active short Positions, specify Position.AllPositions in the pos parameter.
  • The current trailing stop price level is available by accessing the TrailingStop Position property.

Example

protected override void Execute(){
    int period = 20;
    PlotStops();
    for(int bar = period; bar < Bars.Count; bar++)
    {
        if (IsLastPositionActive)
        {
            Position p = LastActivePosition;
            // Protect a 10% gain after giving back 25% to market
            if ( !CoverAtAutoTrailingStop( bar+1, p, 10, 25, "AutoStop" ) )
                // Stop loss at 10%
                CoverAtStop( bar+1, p, p.EntryPrice * 1.10, "Stop Loss" );
        }
        else
            // Enter on channel breakdown
            ShortAtStop( bar+1, Lowest.Series( Low, period )[bar] );
        }
    }
}
BuyAtMarket

CoverAtClose

bool CoverAtClose(int bar, Position pos, string signalName);
bool CoverAtClose(int bar, Position pos);

Covers the short Position specified in the pos parameter at the specified bar, using the closing price of the bar as the exit price.  CoverAtClose will return false if the bar specified is greater than the number of bars on the chart.  In this case, a cover Alert will be generated instead.

Remarks

  • Slippage, when activated, can affect the trade's execution price.
  • The optional signalName parameter will appear in the Strategy window trade list report.
  • To cover all active short Positions, specify Position.AllPositions in the pos parameter.

Example

protected override void Execute(){
    for(int bar = 2; bar < Bars.Count; bar++)
    {
        if (IsLastPositionActive)
        {
            // Exit short after 20 days on close
            if ( bar+1 - LastPosition.EntryBar >= 20 )
                CoverAtClose( bar, LastPosition, "20 day exit" );                    
        }
        else
        {
            //code your entry rules here
            ShortAtStop( bar+1, Low[bar] );
        }
    }
}
BuyAtMarket

CoverAtLimit

bool CoverAtLimit(int bar, Position pos, double limitPrice, string signalName);
bool CoverAtLimit(int bar, Position pos, double limitPrice);

Covers the short Position specified in the pos parameter at the specified bar, using a limit order at the specified limitPrice.  CoverAtLimit returns a bool value indicating whether the price reached the limitPrice or below, and the Position was sold.  CoverAtLimit will also return false if the bar specified is greater than the number of bars on the chart.  In this case, a cover Alert will be generated instead.

Remarks

  • Slippage, when activated, can cause a limit order to fail, even if the price reaches the limitPrice.
  • If the market opens below the limitPrice, the position will be covered at the market open of the bar.
  • The optional signalName parameter will appear in the Strategy window trade list report.
  • To cover all active short Positions, specify Position.AllPositions in the pos parameter.

Example

protected override void Execute(){
    for(int bar = 50; bar < Bars.Count; bar++)
    {
        double adaptiveTarget;
        double big = 4;
        double regular = 1.5;
        if (IsLastPositionActive)
        {
            Position p = LastPosition;
            if ( ROC.Value( bar, ADX.Series( Bars, 14 ), 2 ) > 0 )
            {
                adaptiveTarget = p.EntryPrice - big * ATR.Value( bar, Bars, 20 );
            }
            else
                adaptiveTarget = p.EntryPrice  - regular * ATR.Value( bar, Bars, 20 );
        //  Doubly Adaptive Profit Objective by Chuck LeBeau
            CoverAtLimit( bar + 1, LastPosition, adaptiveTarget, "Adaptive Profit Target" );
        }
        else
        {
            //code your entry rules here
            ShortAtStop( bar+1, Lowest.Value( bar, Low, 20 ) );
        }
    }
}
BuyAtMarket

CoverAtMarket

bool CoverAtMarket(int bar, Position pos, string signalName);
bool CoverAtMarket(int bar, Position pos);

Covers the short Position specified in the pos parameter at the specified bar, using the open price of the bar as the exit price.  CoverAtMarket will return false if the bar specified is greater than the number of bars on the chart.  In this case, a cover Alert will be generated instead.

Remarks

  • Slippage, when activated, can affect the trade's execution price.
  • The optional signalName parameter will appear in the Strategy window trade list report.
  • To cover all active short Positions, specify Position.AllPositions in the pos parameter.

Example

protected override void Execute(){
    DataSeries kl = KeltnerLower.Series( Bars, 10, 10 );
    DataSeries kh = KeltnerUpper.Series( Bars, 10, 10 );
    PlotSeries( PricePane, kh, Color.Blue, LineStyle.Solid, 1 );
    PlotSeries( PricePane, kl, Color.Red, LineStyle.Solid, 1 );
    for(int bar = 50; bar < Bars.Count; bar++)
    {
        if (IsLastPositionActive)
        {
            // Cover at market when price crosses over the Keltner UpperBand
            if ( CrossOver( bar, Close, kh ) )
                CoverAtMarket( bar + 1, LastPosition, "Keltner CrossOver" );
        }
        else
        {
            // Short if close crosses under the Keltner LowerBand
            if ( CrossUnder( bar, Close, kl ) )
                ShortAtMarket( bar + 1, "Keltner CrossUnder" );
        }
    }
}
BuyAtMarket

CoverAtStop

bool CoverAtStop(int bar, Position pos, double stopPrice, string signalName);
bool CoverAtStop(int bar, Position pos, double stopPrice);

Covers the short Position specified in the pos parameter at the specified bar, using a stop order at the specified stopPrice.  CoverAtStop returns a bool value indicating whether the price hit the stopPrice or above, and the Position was covered.  CoverAtStop will also return false if the bar specified is greater than the number of bars on the chart.  In this case, a cover Alert will be generated instead.

Remarks

  • Slippage, when activated, can affect a trade's execution price.
  • If the market open above the stopPrice, the position will be sold at the market open price of the bar.
  • The optional signalName parameter will appear in the Strategy window trade list report.
  • To cover all active short Positions, specify Position.AllPositions in the pos parameter.

Example

protected override void Execute(){
    for(int bar = 20; bar < Bars.Count; bar++)
    {
        if (IsLastPositionActive)
        {
            // Cover the short position if prices move against us by 10%
            CoverAtStop( bar+1, LastPosition, LastPosition.EntryPrice * 1.1, "10% Stop" );
        }
        else
        {
            //code your entry rules here
            ShortAtMarket( bar+1 );
        }
    }
}
BuyAtMarket

CoverAtTrailingStop

bool CoverAtTrailingStop(int bar, Position pos, double stopPrice, string signalName);
bool CoverAtTrailingStop(int bar, Position pos, double stopPrice);

Covers the short Position specified in the pos parameter at the specified bar, using a trailing stop order.  The trailing stop price is maintained with the Position, and it is modified only when the specified stopPrice is below the current trailing stop price.  CoverAtTrailingStop returns a bool value indicating whether the price hit the current trailing stop level or above, and the Position was covered.  CoverAtTrailingStop will also return false if the bar specified is greater than the number of bars on the chart.  In this case, a cover Alert will be generated instead.

Remarks

  • Slippage, when activated, can affect a trade's execution price.
  • If the market open above the current trailing stop price, the position will be covered at the market open price of the bar.
  • The optional signalName parameter will appear in the Strategy window trade list report.
  • To cover all active short Positions, specify Position.AllPositions in the pos parameter.
  • The current trailing stop price level is available by accessing the TrailingStop Position property.

Example

protected override void Execute(){
    PlotStops();
    int period = 20;
    SMA sma = SMA.Series( Close, period );
    PlotSeries( PricePane, sma, Color.BurlyWood, WealthLab.LineStyle.Solid, 1 );
    for(int bar = 3*period; bar < Bars.Count; bar++)
    {
        if (IsLastPositionActive)
        {
            Position p = LastActivePosition;
            // Initiate a trailing stop after a 5% gain
            if ( p.MFEAsOfBarPercent( bar ) > 5 )
            {
                CoverAtTrailingStop( bar+1, p, sma[bar], "Trailing Stop" );
            }
            else
                CoverAtStop( bar+1, p, p.EntryPrice * 1.10, "10% Stop Loss" );
        }
        else
        {
            // sample entry rule
            ShortAtStop( bar+1, sma[bar]*0.97, "3% band around SMA" );
        }
    }
}
BuyAtMarket

ExitAtAutoTrailingStop

bool ExitAtAutoTrailingStop(int bar, Position pos, double triggerPct, double profitReversalPct, string signalName);
bool ExitAtTrailingStop(int bar, Position pos, double triggerPct, double profitReversalPct);

Provides a shortcut that allows you to use a common exit method for both long and short positions.  Internally, ExitAtAutoTrailingStop routes to either SellAtAutoTrailingStop or CoverAtAutoTrailingStop, depending on the PositionType of the Position that was passed to it.


Example

protected override void Execute(){
    double atr, entry, stop;
    int period = 14;     // ATR period
    double mult = 2;    // ATR multiplier        
    for(int bar = period * 2; bar < Bars.Count; bar++)
    {
        atr = ATR.Value( bar, Bars, period ) * mult;
        entry = Bars.Close[bar] + atr;
        if (IsLastPositionActive)
        {
            Position p = LastActivePosition;
            stop = p.EntryPrice;
            // Protect a 10% gain after giving back 25% to market
            if ( !ExitAtAutoTrailingStop( bar+1, p, 10, 25, "AutoStop" ) )
                // Auto-sensing stop loss at 10%
                if ( p.PositionType == PositionType.Long  )
                {
                    stop = p.EntryPrice * 0.9;
                }
                else
                    stop = p.EntryPrice * 1.1;
                ExitAtStop( bar+1, p, stop, "Stop Loss" );
        }
        else
        {
            // "Serendipity entry" (c) Chuck LeBeau
            if ( BuyAtStop( bar+1, entry ) == null )
            {
                entry = Bars.Close[bar] - atr*mult;
                ShortAtStop( bar+1, entry );
            }
        }
    }
}
BuyAtMarket

ExitAtClose

bool ExitAtClose(int bar, Position pos, string signalName);
bool ExitAtClose(int bar, Position pos);

Provides a shortcut that allows you to use a common exit method for both long and short positions.  Internally, ExitAtClose routes to either SellAtClose or CoverAtClose, depending on the PositionType of the Position that was passed to it.


Example

protected override void Execute(){
    // Gap Closer II ( Consecutive Gap Closer )
    bool gapDown, gapUp;
    for(int bar = 4; bar < Bars.Count-1; bar++)
    {
        if (IsLastPositionActive)
        {
            Position p = LastPosition;
            // Take no risk overnight
            ExitAtClose( bar, p );
        }
        else
        {
            // consecutive gap up
            gapUp = ( Bars.Open[bar+1] > Bars.High[bar] ) & 
                ( Bars.Open[bar] > Bars.High[bar-1] ) & 
                // 1st gap not filled
                ( Bars.Low[bar] > Bars.High[bar-1] ) &
                // 1st gap was larger than 2nd gap
                ( ( Bars.Open[bar]-Bars.High[bar-1] ) > ( Bars.Open[bar+1]-Bars.High[bar] ) );
            // consecutive gap down
            gapDown = ( Bars.Open[bar+1] < Bars.Low[bar] ) &
                ( Bars.Open[bar] < Bars.Low[bar-1] ) & 
                // 1st gap not filled
                ( Bars.Low[bar-1] > Bars.High[bar] ) &
                // 1st gap was larger than 2nd gap
                ( ( Bars.Low[bar-1]-Bars.Open[bar] ) > ( Bars.Low[bar]-Bars.Open[bar+1] ) );                    
            // Buy/short the gap
            if ( gapDown ) 
                BuyAtMarket( bar+1, "Gap Down" );
            else if ( gapUp ) 
                ShortAtMarket( bar+1, "Gap Up" );
        }
    }
}
BuyAtMarket

ExitAtLimit

bool ExitAtLimit(int bar, Position pos, double limitPrice, string signalName);
bool ExitAtLimit(int bar, Position pos, double limitPrice);

Provides a shortcut that allows you to use a common exit method for both long and short positions.  Internally, ExitAtLimit routes to either SellAtLimit or CoverAtLimit, depending on the PositionType of the Position that was passed to it.


Example

protected override void Execute(){
    double entry, profit;
    int period = 10;     // period
    double mult = 2;    // ATR multiplier
    DataSeries hi = Highest.Series(High, period);
    DataSeries lo = Lowest.Series(Low, period);
    for(int bar = 20; bar < Bars.Count; bar++)
    {
        // Exit either position at limit @ entry price +/- 2 times the 20-period ATR
        if (IsLastPositionActive)
        {
            Position p = LastPosition;
            // The power of "?" ternary operator:
            profit = (LastPosition.PositionType == PositionType.Long) ? p.EntryPrice + ATR.Value(bar, Bars, period) * mult : profit = p.EntryPrice - ATR.Value(bar, Bars, period) * mult;
            ExitAtLimit( bar, LastPosition, profit );
        }
        else
        {
            // plain vanilla channel breakout
            if ( BuyAtStop( bar+1, hi[bar], "Long" ) == null )
            {
                ShortAtStop( bar+1, lo[bar], "Short" );
            }
        }
    }
}
BuyAtMarket

ExitAtMarket

bool ExitAtMarket(int bar, Position pos, string signalName);
bool ExitAtMarket(int bar, Position pos);

Provides a shortcut that allows you to use a common exit method for both long and short positions.  Internally, ExitAtMarket routes to either SellAtMarket or CoverAtMarket, depending on the PositionType of the Position that was passed to it.


Example

protected override void Execute(){
    int period = 20;    // SMA period
    bool Event;
    DataSeries sma = SMA.Series( Close, period );
    DataSeries hi = Highest.Series(High, period);
    DataSeries lo = Lowest.Series(Low, period);
    PlotSeries( PricePane, hi, Color.Blue, WealthLab.LineStyle.Dotted, 2 );
    PlotSeries( PricePane, lo, Color.Red, WealthLab.LineStyle.Dotted, 2 );
    PlotSeries( PricePane, sma, Color.DarkGreen, WealthLab.LineStyle.Solid, 2 );
    for(int bar = 20; bar < Bars.Count; bar++)
    {
        // Exit position at market on a SMA CrossUnder/CrossOver
        if (IsLastPositionActive)
        {
            Position p = LastPosition;
            // Ternary operator "?" fits with the Exit* operator syntax
            Event = ( LastPosition.PositionType == PositionType.Long ) ? ( CrossUnder( bar, Close, sma ) ) : ( CrossOver( bar, Close, sma ) );
            if ( Event )
            {
                ExitAtMarket( bar+1, p );
            }
        }
        else
        {
            // plain vanilla channel breakout
            if ( BuyAtStop( bar+1, hi[bar] ) == null )
            {
                ShortAtStop( bar+1, lo[bar] );
            }
        }
    }
}
BuyAtMarket

ExitAtStop

bool ExitAtStop(int bar, Position pos, double stopPrice, string signalName);
bool ExitAtStop(int bar, Position pos, double stopPrice);

Provides a shortcut that allows you to use a common exit method for both long and short positions.  Internally, ExitAtStop routes to either SellAtStop or CoverAtStop, depending on the PositionType of the Position that was passed to it.


Example

protected override void Execute(){
    double entry, level;
    int period = 20;     // period
    double mult = 3;    // ATR multiplier
    DataSeries hi = Highest.Series(High, period );
    DataSeries lo = Lowest.Series(Low, period );
    DataSeries atr = ATR.Series( Bars, period );
    for(int bar = 20; bar < Bars.Count; bar++)
    {
        // Exit position at a respective Chandelier stop
        if (IsLastPositionActive)
        {
            Position p = LastPosition;
            level = (LastPosition.PositionType == PositionType.Long) ? hi[bar] - (atr[bar] * mult ) : lo[bar] + (atr[bar] * mult );
            ExitAtStop( bar+1, p, level, "Chandelier exit" );
        }
        else
        {
            // plain vanilla channel breakout
            if ( BuyAtStop( bar+1, hi[bar], "Long" ) == null )
            {
                ShortAtStop( bar+1, lo[bar], "Short" );
            }
        }
    }
}
BuyAtMarket

ExitAtTrailingStop

bool ExitAtTrailingStop(int bar, Position pos, double stopPrice, string signalName);
bool ExitAtTrailingStop(int bar, Position pos, double stopPrice);

Provides a shortcut that allows you to use a common exit method for both long and short positions.  Internally, ExitAtTrailingStop routes to either SellAtTrailingStop or CoverAtTrailingStop, depending on the PositionType of the Position that was passed to it.


Example

protected override void Execute(){
    double entry, level;
    int period = 20;     // period
    double mult = 3;    // ATR multiplier
    DataSeries hi = Highest.Series( High, period );
    DataSeries lo = Lowest.Series(Low, period );
    DataSeries atr = ATR.Series( Bars, period );
    PlotStops();
    for(int bar = 20; bar < Bars.Count; bar++)
    {
        // Exit position at respective Chandelier stop
        if (IsLastPositionActive)
        {
            Position p = LastPosition;
            level = ( LastPosition.PositionType == PositionType.Long ) ? hi[bar] - ( atr[bar] * mult ) : lo[bar] + (atr[bar] * mult );
            ExitAtTrailingStop( bar+1, p, level, "Trailing Chandelier" );
        }
        else
        {
            // plain vanilla channel breakout
            if ( BuyAtStop( bar+1, hi[bar] ) == null )
            {
                ShortAtStop( bar+1, lo[bar] );
            }
        }
    }
}
BuyAtMarket

RiskStopLevel Property

double RiskStopLevel

Specifies the initial stop level (price) for the next Position to be created. This stop level is used when you select the Maximum Risk Pct Position Sizing option.  This option specifies the maximum amount of capital you are willing to risk on each trade.  When this option is selected, you must set the value of RiskStopLevel in your Strategy code to indicate the initial stop loss value for a newly created Position.

For example, a simple channel breakout system might enter at the highest 20 bar high, and exit at the lowest 20 bar low.  Prior to issuing the BuyAtMarket, or BuyAtStop, you should set RiskStopLevel to the lowest Low value of the past 20 bars as the initial stop level for the long Position.

Remarks

  • If you select the Maximum Risk Pct position sizing option and do not set RiskStopLevel in your Strategy code, you will receive an error message when attempting to run the Strategy.
  • You must also be diligent in your Strategy to actually use the established stop level as an exit.  If you do not, the Strategy could lose considerably more than the Maximum Risk that you established in the Position Size setting.
  • Once a RiskStopLevel is established for a Position, do not change it. The [last] value assigned to a Position's RiskStopLevel is used to determine % Risk sizing, consequently reassigning its value after the Position is established is effectively a peeking error.

Example

protected override void Execute(){
    PlotStops();
    for(int bar = 30; bar < Bars.Count; bar++)
    {
        ATR atr = ATR.Series( Bars, 14 );
        if (IsLastPositionActive)
        {
            Position p = LastPosition;
            // Protective stop: "Yo-Yo Exit" by Chuck LeBeau
            SellAtStop( bar+1, p, p.RiskStopLevel, "Yo-Yo Stop" );
            SellAtLimit( bar+1, p, p.EntryPrice*1.1, "10% profit" );
        }
        else
        {
            //Set our risk stop at an ATR unit below the last day's low
            RiskStopLevel = ( Bars.Low[bar] - 1*atr[bar] );
            BuyAtStop( bar+1, Bars.Close[bar]+2*atr[bar], "Volatility Breakout" );
        }
    }
}

SellAtAutoTrailingStop

bool SellAtAutoTrailingStop(int bar, Position pos, double triggerPct, double profitReversalPct, string signalName);
bool SellAtAutoTrailingStop(int bar, Position pos, double triggerPct, double profitReversalPct);

Sells the Position specified in the pos parameter at the specified bar, using a trailing stop order.  The trailing stop is initiated only after the position reaches the profit level specified in the triggerPct parameter. The stop price is calculated based on the profitReversalPct parameter.  This value indicates the percentage reversal in the Position's profit that should be used as a stop level.

For example, assume we specify 30 for profitReversalPct, and our Position had an entry price of $10 and is currently at $12 (a 20% profit so far).

The total profit so far is $12 - $10 = $2

30% of $2 is $0.60

The stop order will be placed at $12 - $0.60 = $11.40

The trailing stop price is maintained with the Position, and it is modified only when the calculated stop price is above the current trailing stop price.  SellAtAutoTrailingStop returns a bool value indicating whether the price hit the current trailing stop level or below, and the Position was sold.  SellAtAutoTrailingStop will also return false if the bar specified is greater than the number of bars on the chart.  In this case, a sell Alert will be generated instead.

Remarks

  • Slippage, when activated, can affect a trade's execution price.
  • If the market open below the current trailing stop price, the position will be sold at the market open price of the bar.
  • The optional signalName parameter will appear in the Strategy window trade list report.
  • To sell all active long Positions, specify Position.AllPositions in the pos parameter.
  • The current trailing stop price level is available by accessing the TrailingStop Position property.

Example

protected override void Execute(){
    int period = 20;
    DataSeries kama = KAMA.Series( Bars.Close, 20 );
    PlotStops();
    for(int bar = period*3; bar < Bars.Count; bar++)
    {
        if (IsLastPositionActive)
        {
            Position p = LastActivePosition;
            // Protect a 10% gain after giving back 25% to market
            if ( !SellAtAutoTrailingStop( bar+1, p, 10, 25, "10% AutoStop" ) )
                SellAtStop( bar+1, p, p.EntryPrice * 0.90, "10% stop loss" );
        }
        else
            // Enter when closing cross over KAMA
            if ( CrossOver( bar, Close, kama ) )
                BuyAtStop( bar+1, Close[bar] );
    }
}
BuyAtMarket

SellAtClose

bool SellAtClose(int bar, Position pos, string signalName);
bool SellAtClose(int bar, Position pos);

Sells the Position specified in the pos parameter at the specified bar, using the closing price of the bar as the exit price.  SellAtClose will return false if the bar specified is greater than the number of bars on the chart.  In this case, a sell Alert will be generated instead.

Remarks

  • Slippage, when activated, can affect the trade's execution price.
  • The optional signalName parameter will appear in the Strategy window trade list report.
  • To sell all active long Positions, specify Position.AllPositions in the pos parameter.

Example

protected override void Execute(){
    for(int bar = 2; bar < Bars.Count; bar++)
    {
        if (IsLastPositionActive)
        {
            // Exit long after 20 days 
            if ( bar+1 - LastPosition.EntryBar >= 20 )
                SellAtClose( bar, LastPosition, "20 day exit" );                    
        }
        else
        {
            //code your entry rules here
            BuyAtStop( bar+1, High[bar] );
        }
    }
}
BuyAtMarket

SellAtLimit

bool SellAtLimit(int bar, Position pos, double limitPrice, string signalName);
bool SellAtLimit(int bar, Position pos, double limitPrice);

Sells the Position specified in the pos parameter at the specified bar, using a limit order at the specified limitPrice.  SellAtLimit returns a bool value indicating whether the price reached the limitPrice or above, and the Position was sold.  SellAtLimit will also return false if the bar specified is greater than the number of bars on the chart.  In this case, a sell Alert will be generated instead.

Remarks

  • Slippage, when activated, can cause a limit order to fail, even if the price reaches the limitPrice.
  • If the market opens above the limitPrice, the position will be sold at the market open of the bar.
  • The optional signalName parameter will appear in the Strategy window trade list report.
  • To sell all active long Positions, specify Position.AllPositions in the pos parameter.

Example

protected override void Execute(){
    DataSeries high = Highest.Series( High, 10 );
    DataSeries ema1 = EMA.Series( Close, 2, WealthLab.Indicators.EMACalculation.Modern );
    DataSeries ema2 = EMA.Series( Close, 10, WealthLab.Indicators.EMACalculation.Modern );
    PlotSeries( PricePane, ema1, Color.LightBlue, WealthLab.LineStyle.Solid, 2 );
    PlotSeries( PricePane, ema2, Color.ForestGreen, WealthLab.LineStyle.Solid, 2 );
    for(int bar = 30; bar < Bars.Count; bar++)
    {
        if (IsLastPositionActive)
        {
            // Try to get out at a recent high + some percent
            if ( SellAtLimit( bar+1, LastPosition, high[bar]*1.02, "Limit Sell" ) )
                PrintDebug( "Sold" );
        }
        else
        {
            // "Anti-Trend EMA" entry
            if ( CrossUnder( bar, ema1, ema2 ) )
                BuyAtMarket( bar+1 );
        }
    }
}
BuyAtMarket

SellAtMarket

bool SellAtMarket(int bar, Position pos, string signalName);
bool SellAtMarket(int bar, Position pos);

Sells the Position specified in the pos parameter at the specified bar, using the open price of the bar as the exit price.  SellAtMarket will return false if the bar specified is greater than the number of bars on the chart.  In this case, a sell Alert will be generated instead.

Remarks

  • Slippage, when activated, can affect the trade's execution price.
  • The optional signalName parameter will appear in the Strategy window trade list report.
  • To sell all active long Positions, specify Position.AllPositions in the pos parameter.

Example

protected override void Execute(){
    int shift = 4;
    DataSeries dma1 = SMA.Series( Close, 7 ) >> shift;
    DataSeries dma2 = SMA.Series( Close, 25 ) >> shift;
    PlotSeries( PricePane, dma1, Color.Green, LineStyle.Solid, 1);
    PlotSeries( PricePane, dma2, Color.Blue, LineStyle.Solid, 1);
    for(int bar = 30; bar < Bars.Count; bar++)
    {
        if (IsLastPositionActive)
        {
            // Displaced Moving Average (DMA) strategy exit
            if ( CrossUnder( bar, dma1, dma2 ) )
                SellAtMarket( bar+1, LastPosition, "DMA CrossUnder" );
        }
        else
        {
            // Displaced Moving Average (DMA) strategy entry
            if ( CrossOver( bar, dma1, dma2 ) )
                BuyAtMarket( bar+1, "DMA CrossOver" );
        }
    }
}
BuyAtMarket

SellAtStop

bool SellAtStop(int bar, Position pos, double stopPrice, string signalName);
bool SellAtStop(int bar, Position pos, double stopPrice);

Sells the Position specified in the pos parameter at the specified bar, using a stop order at the specified stopPrice.  SellAtStop returns a bool value indicating whether the price hit the stopPrice or below, and the Position was sold.  SellAtStop will also return false if the bar specified is greater than the number of bars on the chart.  In this case, a sell Alert will be generated instead.

Remarks

  • Slippage, when activated, can affect a trade's execution price.
  • If the market open below the stopPrice, the position will be sold at the market open price of the bar.
  • The optional signalName parameter will appear in the Strategy window trade list report.
  • To sell all active long Positions, specify Position.AllPositions in the pos parameter.

Example

protected override void Execute(){
    for(int bar = 20; bar < Bars.Count; bar++)
    {
        if (IsLastPositionActive)
        {
            Position p = LastPosition;    
            // Cover the long position if prices move against us by 7%
            SellAtStop( bar+1, p, p.EntryPrice * 0.93, "7% Stop" );
        }
        else
        {
            //code your entry rules here
            BuyAtMarket( bar+1 );
        }
    }
}
BuyAtMarket

SellAtTrailingStop

bool SellAtTrailingStop(int bar, Position pos, double stopPrice, string signalName);
bool SellAtTrailingStop(int bar, Position pos, double stopPrice);

Sells the Position specified in the pos parameter at the specified bar, using a trailing stop order.  The trailing stop price is maintained with the Position, and it is modified only when the specified stopPrice is above the current trailing stop price.  SellAtTrailingStop returns a bool value indicating whether the price hit the current trailing stop level or below, and the Position was sold.  SellAtTrailingStop will also return false if the bar specified is greater than the number of bars on the chart.  In this case, a sell Alert will be generated instead.

Remarks

  • Slippage, when activated, can affect a trade's execution price.
  • If the market open below the current trailing stop price, the position will be sold at the market open price of the bar.
  • The optional signalName parameter will appear in the Strategy window trade list report.
  • To sell all active long Positions, specify Position.AllPositions in the pos parameter.
  • The current trailing stop price level is available by accessing the TrailingStop Position property.

Example

protected override void Execute(){
    PlotStops();
    int period = 20;
    DataSeries atr = ATR.Series( Bars, period );
    for(int bar = period; bar < Bars.Count; bar++)
    {
        if (IsLastPositionActive)
        {
            Position p = LastActivePosition;
            SellAtStop( bar+1, p, p.EntryPrice * 0.95, "5% Stop Loss" );
            // Trailing Chandelier exit (Chuck LeBeau) at 40-bar highest high minus 3 ATR units
            SellAtTrailingStop( bar+1, p, Highest.Series( High, period )[bar]-3*atr[bar], "Trailing Stop" );
        }
        else
        {
            // sample entry rule
            BuyAtStop( bar+1, Highest.Series( High, period )[bar] );
        }
    }
}
BuyAtMarket

SetShareSize

double SetShareSize( double shares )

Use SetShareSize to assign a fixed number of Shares (or contracts) per Position in your Strategy. Subsequent trades will use the number of Shares or contracts that you specified.

Remarks

  • In Raw Profit modes, SetShareSize does not have effect. It applies to Portfolio Simulation mode only.
  • When using SetShareSize, you must choose the radio button for WealthScript Override (SetShareSize) in the Position Sizing control to enable SetShareSize to influence position sizing.

Example

protected override void Execute(){
SMA sma = SMA.Series( Close, 50 );
            
            for(int bar = sma.FirstValidValue; bar < Bars.Count; bar++)
            {
                if (IsLastPositionActive)
                {
                    /* Exit after N days */
                    
                    Position p = LastPosition;
                    if ( bar+1 - p.EntryBar >= 3 )
                        SellAtMarket( bar+1, p, "Timed" ); 
                }
                else
                {
                    /* When the Close is below the SMA,
                    size the new position twice the normal */
                    
                    if( Close[bar] > sma[bar] )
                        SetShareSize( 1000 );
                    else
                        SetShareSize( 2000 );
                    
                    BuyAtLimit( bar+1, Close[bar]*0.93 );
                }
            }
        }
    }
}
BuyAtMarket

ShortAtClose

Position ShortAtClose(int bar, string signalName);
Position ShortAtClose(int bar);

Enters a new short position at the specified bar, using the closing price of the bar as the entry price.  The position size will be calculated based on the closing price of the previous bar.  Returns a new Position object that represents the newly established short position.

Remarks

  • Slippage, when activated, can affect the trade's execution price.
  • The optional signalName parameter will appear in the Strategy window trade list report.

Example

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

namespace WealthLab.Strategies
{
    public class ShortAtCloseDemo : WealthScript
    {
        //Lowest Low parameter
        private StrategyParameter per;

        public ShortAtCloseDemo()
        {
            per = CreateParameter("CumUp period, days", 10, 10, 30, 5);
        }

        protected override void Execute()
        {
            //Obtain period from parameter
            int period = per.ValueInt;
            
            CumUp cumUp = CumUp.Series( Bars.Close, period );
            ChartPane cu = CreatePane( 50, true, false );
            PlotSeries( cu, cumUp, Color.Red, WealthLab.LineStyle.Dotted, 2 );
            
            for(int bar = period; bar < Bars.Count; bar++)
            {
                if (!IsLastPositionActive)
                {
                    if( Close[bar] > SMA.Series( Close,2 )[bar] )
                        // Short at Close on CumUp >= 5 in 10 bars
                        if( cumUp[bar] >= 5 )
                            ShortAtClose( bar );
                }
                if (IsLastPositionActive)
                {
                    // .. Exit Rules ...
                    CoverAtMarket( bar+1, LastPosition );
                }
            }
        }
    }
}
BuyAtMarket

ShortAtLimit

Position ShortAtLimit(int bar, double limitPrice, string signalName);
Position ShortAtLimit(int bar, double limitPrice);

Enters a new short position at the specified bar, using a limit order at the specified limitPrice.  The position size will be calculated based on the limitPrice.  If the price of the bar reaches the limitPrice or higher, ShortAtLimit returns a new Position object that represents the newly established short position.  If the limitPrice was not reached, ShortAtLimit returns null.

Remarks

  • Slippage, when activated, can cause limit orders to fail, even if the price of the bar reaches the limitPrice.
  • If the market open above the limitPrice, the entry price of the position will be set to the market open price of the bar.
  • The optional signalName parameter will appear in the Strategy window trade list report.

Example

protected override void Execute(){
    Bars benchmark = GetExternalSymbol( "QQQQ", true );
    ChartPane mkt = CreatePane( 35, true, false );
    DataSeries adx = ADX.Series( Bars, 14 );
    DataSeries adx_market = ADX.Series( benchmark, 14 );
    DataSeries diP = DIPlus.Series( Bars, 14 );
    DataSeries diM = DIMinus.Series( Bars, 14 );
    PlotSeries( mkt, adx, Color.Red, WealthLab.LineStyle.Solid, 1 );
    PlotSeries( mkt, adx_market, Color.DarkRed, WealthLab.LineStyle.Solid, 2 );
    for(int bar = 30; bar < Bars.Count; bar++)
    {
        if (!IsLastPositionActive)
        {
            // Short symbol when it lags some general market benchmark
            if( adx[bar] < adx_market[bar] )
                if( diP[bar] < diM[bar] )
                    // Short next bar at the limit of 20-period high
                    ShortAtLimit( bar+1, Lowest.Value( bar, Bars.High, 20 ), "Short @ Limit" );
        }
        if (IsLastPositionActive)
        {
            //code your exit rules here
            //...
        }
    }
}
BuyAtMarket

ShortAtMarket

Position ShortAtMarket(int bar, string signalName);
Position ShortAtMarket(int bar);

Enters a new short position at the specified bar, using the open price of the bar as the entry price.  The position size will be calculated based on the closing price of the previous bar.  Returns a new Position object that represents the newly established short position.

Remarks

  • Slippage, when activated, can affect the trade's execution price.
  • The optional signalName parameter will appear in the Strategy window trade list report.

Example

protected override void Execute(){
    DataSeries rsi = RSI.Series( Close, 14 );
    ChartPane rsiPane = CreatePane( 40, true, false );
    PlotSeries( rsiPane, rsi, Color.Chartreuse, WealthLab.LineStyle.Dotted, 2 );
    DrawHorzLine( rsiPane, 70, Color.Red, WealthLab.LineStyle.Dashed, 1 );
    for(int bar = 30; bar < Bars.Count; bar++)
    {
        if (IsLastPositionActive)
        {
            // Exit after 10 days
            if ( bar+1 - LastPosition.EntryBar == 10 )
                CoverAtMarket( bar+1, LastPosition, "Time-Based" );
        }
        else
        {
            // Establish a short position if RSI gets overbought
            if ( RSI.Series( Close, 14 )[bar] > 70 )
                ShortAtMarket( bar+1, "RSI Short Signal" );
        }
    }
}
BuyAtMarket

ShortAtStop

Position ShortAtStop(int bar, double stopPrice, string signalName);
Position ShortAtStop(int bar, double stopPrice);

Enters a new short position at the specified bar, using a stop order at the specified stopPrice.  The position size will be calculated based on the stopPrice.  If the price of the bar reaches the stopPrice or lower, ShortAtStop returns a new Position object that represents the newly established short position.  If the stopPrice was not reached, ShortAtStop returns null.

Remarks

  • Slippage, when activated, can affect the trade's execution price.
  • If the market open below the stopPrice, the entry price of the position will be set to the market open price of the bar.
  • The optional signalName parameter will appear in the Strategy window trade list report.

Example

protected override void Execute(){
    for(int bar = 5; bar < Bars.Count; bar++)
    {
        if (!IsLastPositionActive)
        {
            // "Oops" ( Larry Williams )
            if ( Bars.Open[bar] > Bars.High[bar-1] )
                ShortAtStop( bar, Bars.Low[bar-1], "Oops" );                    
        }
        if (IsLastPositionActive)
            ExitAtClose( bar, LastPosition );
    }
}