Profile Picture

LowestLow/HighestHigh Trading System

Posted By alex_n 5 Years Ago
Message
Posted Friday February 17 2012
Hello,
I'm a newbie here and I have a problem with reversing a position from long to short and short to long on the same bar with a simple trading system, based on LL and HH channels.

I need to buy on Highest High for the last 80 bars and reverse a position to short on Lowest Low for the 80 bars. Unfortunately, I couldn't do that: initiating a new position always comes on a new bar, but not on the bar of exit.
As an example I took Indicator Based Stop and Reverse trading system.

Can anyone help me what I'm doing wrong and how to make a strategy to reverse on the bar the same bar?

Thanks in advance



#region Using statements
using System;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using RightEdge.Common;
using RightEdge.Common.ChartObjects;
using RightEdge.Indicators;
#endregion

#region System class
public class MySystem : MySystemBase
{
   public override void Startup()
   {
      // Perform initialization or set system wide options here
      PositionManager.PositionOverfilledAction = PositionAction.DoNothing;
   }
}
#endregion

public class MySymbolScript : MySymbolScriptBase
{
   #region Variables
   Lowest LL;
   Highest HH;
   int LL_Per;
   int HH_Per;
   
   // Signals
   bool signalLong = false;
   bool signalShort = false;
   double signalCover;
   double signalSell;
   private Position currentPosition = null;

   bool flat;
   
   int minBars = 20;
      
   #endregion
   
   public override void Startup()
   {
      // Perform initialization here.
      LL_Per = (int)SystemParameters["LL_Per"];
      HH_Per = (int)SystemParameters["HH_Per"];
      
      LL = new Lowest (LL_Per, Low);
      LL.ChartSettings.Color = Color.Red;
      LL.ChartSettings.DisplayName = "LL";
      
      HH = new Highest (HH_Per, High);
      HH.ChartSettings.Color = Color.Brown;
      HH.ChartSettings.DisplayName = "HH";

   }

   public override void NewBar()
   {

      // Put your trading code here

      minBars = Math.Max(LL_Per, HH_Per);

      //minimum Bars check
      if (Bars.Count < minBars)
      {
         return; //Not enough data yet to have an indicator value; so don't trade
      }

      flat = (OpenPositions.Count == 0);

      signalLong = (High.Current > HH.LookBack(1));
      signalShort = (Low.Current < LL.LookBack(1));
      signalCover = HH.Current;
      signalSell = LL.Current;

      //Stops Sections

      if (!flat)
      {
         foreach (Position position in OpenPositions)
         {
            if (position.Type == PositionType.Long)
            {
               position.SetStopLossPrice(signalSell);
            }
            else
            {
               position.SetStopLossPrice(signalCover);
            }
         }
      }
      else
      {
         if (signalLong == true)
         {
      
            PositionSettings lps = new PositionSettings();
            
            // Go long
            lps.PositionType = PositionType.Long;
            lps.Description = "Buy";
            lps.BarsValid = -1;
            lps.OrderType = OrderType.Stop;
            lps.StopPrice = HH.Current;

            if (flat)
            {
               currentPosition = OpenPosition(lps);
               if ((currentPosition != null) && (currentPosition.Error != null))
               {
                  OutputWarning(currentPosition.Error);
               }
            }
         }
         else if (signalShort == true)
         {

            PositionSettings sps = new PositionSettings();
            sps.PositionType = PositionType.Short;
            sps.Description = "Short";
            sps.BarsValid = -1;
            sps.OrderType = OrderType.Stop;
            sps.StopPrice = LL.Current;

            if (flat == true)
            {
               currentPosition = OpenPosition(sps);
               if ((currentPosition != null) && (currentPosition.Error != null))
               {
                  OutputWarning(currentPosition.Error);
               }
            }
         }
      }
   }

   public override void OrderFilled(Position position, Trade trade)
   {
      // This method is called when an order is filled

      if ((OpenPositions.Count == 1) && (trade.TransactionType == TransactionType.Cover)) //(trade.OrderType == OrderType.Stop))
      {
         //Cover Short and Open Long
         PositionSettings long_reverse = new PositionSettings();
         long_reverse.PositionType = PositionType.Long;
         long_reverse.OrderType = OrderType.Stop;
         //long_reverse.StopPrice = HH.Current;
         long_reverse.StopPrice = position.ExitPrice.SymbolPrice;
         long_reverse.Description = "Long Reverse";
         long_reverse.BarsValid = -1;

         currentPosition = OpenPosition(long_reverse);
      }
      else if ((OpenPositions.Count == 1) && (trade.TransactionType == TransactionType.Sell)) //(trade.OrderType == OrderType.Stop))
      {
         //Sell and Open Short
         PositionSettings short_reverse = new PositionSettings();
         short_reverse.PositionType = PositionType.Short;
         short_reverse.OrderType = OrderType.Stop;
         //short_reverse.StopPrice = LL.Current;
         short_reverse.StopPrice = position.ExitPrice.SymbolPrice;
         short_reverse.Description = "Short Reverse";
         short_reverse.BarsValid = -1;

         currentPosition = OpenPosition(short_reverse);
      }
   }

   public override void OrderCancelled(Position position, Order order, string information)
   {
      // This method is called when an order is cancelled or rejected
if (!order.CancelPending)
{
OutputWarning("Unexpected order cancel: " + order.ToString() + " " + information);
}
   }
}


Posted Saturday February 18 2012
Anyone can help? Is it possible to reverse on the same bar (not overfilling with the same size like in Indicator Based Stop and Reverse example).

Thanks in advance
Posted Sunday February 19 2012
See this post for information on how to do this: Closing previous position and opening new position

Basically, you need to enable the BarClosing event and submit your orders in response to this event for them to be filled on the close of the current bar. Further down in the thread I linked to is a sample system in C# that does this. For your system, you should copy the Startup() and BarClosing() methods from the MySystem class, and move all your trading logic that is in your NewBar() method to a BarClosing() method in your MySymbolScript class.

Let us know if you have any trouble.

Thanks,
Daniel
Posted Monday February 20 2012
As I understand it, alex_n wants to be able to enter into a new position immediately after the stop-loss and at the same price.

I wrote a simple strategy for example, and also failed to achieve the desired result. Sometimes everything works as it should, sometimes a new position is opened only on the next bar. Information from the link above did not help.


#region System class

public class MySystem : MySystemBase
{
   public override void Startup()
   {
      // Perform initialization or set system wide options here
      //SystemData.EnableTradeOnClose = true;
      //SystemData.BarClosing += BarClosing;
   }

   void BarClosing(object sender, NewBarEventArgs args)
   {
      foreach (MySymbolScript symbolScript in SymbolScripts)
      {
         symbolScript.BarClosing();
      }
   }
}

#endregion

public class MySymbolScript : MySymbolScriptBase
{
   Position currentPosition;
   int positionCount = 0;

   public override void Startup()
   {
   }

   public void BarClosing()
   {
   }

   public override void NewBar()
   {
      if (SystemData.InLeadBars == false)
      {
         if ((OpenPositions.Count == 1) && (positionCount == 1))
         {
            OpenPositions[0].SetStopLoss(OpenPositions[0].EntryPrice.SymbolPrice + 1.1, TargetPriceType.AbsolutePrice);
         }

         if (positionCount == 0)
         {
            // open new Long
            PositionSettings ps = new PositionSettings();
            ps.OrderType = OrderType.Market;
            ps.Description = "SE";
            ps.PositionType = PositionType.Short;
            //ps.Description = "LE";
            //ps.PositionType = PositionType.Long;

            currentPosition = OpenPosition(ps);

            positionCount++;
         }
      }
   }

   public override void OrderFilled(Position position, Trade trade)
   {
      if ((positionCount == 1) && (trade.OrderType == OrderType.Stop))
      {
         if (trade.TransactionType == TransactionType.Cover)
         {
            // open new Long
            PositionSettings ps = new PositionSettings();
            ps.Description = "LE";
            ps.LimitPrice = position.ExitPrice.SymbolPrice;
            ps.OrderType = OrderType.Limit;
            //ps.StopPrice = position.ExitPrice.SymbolPrice;
            //ps.OrderType = OrderType.Stop;
            ps.PositionType = PositionType.Long;

            currentPosition = OpenPosition(ps);

            positionCount++;
         }
         else if (trade.TransactionType == TransactionType.Sell)
         {
            // open new Short
            PositionSettings ps = new PositionSettings();
            ps.Description = "SE";
            ps.LimitPrice = position.ExitPrice.SymbolPrice;
            ps.OrderType = OrderType.Limit;
            ps.PositionType = PositionType.Short;

            currentPosition = OpenPosition(ps);

            positionCount++;
         }
      }
   }

   public override void OrderCancelled(Position position, Order order, string information)
   {
      // This method is called when an order is cancelled or rejected
      if (!order.CancelPending)
      {
         OutputWarning("Unexpected order cancel: " + order.ToString() + " " + information);
      }
   }
}


I am also interested to know how to achieve the desired result.

PS. Tested on AA ticker. Different results can be obtained by changing the stop-loss level, start/end dates.
Posted Wednesday February 22 2012
Daniel, thank you for the link with the example.

I tried your code and when I try to add my conditions, I get an error:
An exception of type System.InvalidOperationException was thrown.
Sequence contains more than one element
at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source)
at MySymbolScript.BarClosing() in line 104

My idea is to open long at the highest high for 80 bars and reverse (close long&open short) at the lowest low for 80 bars, and vice verse. Actually, as JoeChangSi noticed, I want to reverse during the bars, not at the close.

Can you, please look at my new script and correct it where it is necessary.
Thanks in advance

#region Using statements

using System;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using RightEdge.Common;
using RightEdge.Common.ChartObjects;
using RightEdge.Indicators;
#endregion

#region System class

public class MySystem : MySystemBase
{
   public override void Startup()
   {
      // Perform initialization or set system wide options here
      SystemData.EnableTradeOnClose = true;
      SystemData.BarClosing += BarClosing;
   }
   
   void BarClosing(object sender, NewBarEventArgs args)
   {
      foreach (MySymbolScript symbolScript in SymbolScripts)
      {
         symbolScript.BarClosing();
      }
   }
}

#endregion

public class MySymbolScript : MySymbolScriptBase

{
   #region Variables

   Lowest LL;
   Highest HH;

   int LL_Per;
   int HH_Per;

   // Signals
   bool signalLong = false;
   bool signalShort = false;
   double signalCover;
   double signalSell;

   private Position currentPosition = null;
   private PositionType desiredPosition;
   int minBars = 20;

   #endregion

   public override void Startup()

   {
      // Perform initialization here.

      LL_Per = (int)SystemParameters["LL_Per"];
      HH_Per = (int)SystemParameters["HH_Per"];

      LL = new Lowest (LL_Per, Low);
      LL.ChartSettings.Color = Color.Red;
      LL.ChartSettings.DisplayName = "LL";
      
      HH = new Highest (HH_Per, High);
      HH.ChartSettings.Color = Color.Brown;
      HH.ChartSettings.DisplayName = "HH";
   }

   public override void NewBar()
   {
   }
   
   public void BarClosing()
   {
      // Put your trading code here

      minBars = Math.Max(LL_Per, HH_Per);
      
      //minimum Bars check

      if (Bars.Count < minBars)
      {
         return; //Not enough data yet to have an indicator value; so don't trade
      }

   Position pos = OpenPositions.SingleOrDefault();

      signalLong = (High.Current > HH.LookBack(1));
      signalShort = (Low.Current < LL.LookBack(1));
      signalCover = HH.Current;
      signalSell = LL.Current;

      if (signalLong == true)
      {
         desiredPosition = PositionType.Long;

      }
      else if (signalShort == true)
      {
         desiredPosition = PositionType.Short;
      }
      if (pos != null && pos.Type == desiredPosition)
      {
         //Do Nothing, already in position
      }
      else
      {
         if (pos != null && desiredPosition == PositionType.Long)
            {
             pos.SetStopLossPrice(signalSell);
             PositionSettings sps = new PositionSettings();
            sps.PositionType = PositionType.Short;
            sps.Description = "Short";
             sps.BarsValid = -1;
             sps.OrderType = OrderType.Stop;
             sps.StopPrice = LL.Current;
             currentPosition = OpenPosition(sps);
            }
            else
            {
               if (pos != null && desiredPosition == PositionType.Short)
               {
                  pos.SetStopLossPrice(signalSell);
                  PositionSettings lps = new PositionSettings();
                  lps.PositionType = PositionType.Long;
                  lps.Description = "Buy";
                  lps.BarsValid = -1;
                  currentPosition = OpenPosition(lps);
                  lps.OrderType = OrderType.Stop;
                  lps.StopPrice = HH.Current;
                OpenPosition (lps);
               }
            }
       OpenPosition (desiredPosition, OrderType.Market);      
      }
   }

   
   public override void OrderFilled(Position position, Trade trade)
   {
      // This method is called when an order is filled
   }

   public override void OrderCancelled(Position position, Order order, string information)
   {
      // This method is called when an order is cancelled or rejected
if (!order.CancelPending)
{
OutputWarning("Unexpected order cancel: " + order.ToString() + " " + information);
}
   }
}

Edited: Wednesday February 22 2012 by alex_n
Posted Thursday February 23 2012
Daniel, any suggestions? Is my idea realizable in RE?
Thanks
Posted Sunday February 26 2012
Hi Alex,

Sorry, I didn't quite understand what you were trying to do the first time. If I'm understanding correctly this time, then you don't need to use bar closing at all. You just need to have your stop order be twice the size of your position so that when it is filled it will close the current position and open a position in the other direction. (Of course, if you want to adjust the position size, then it should be the size of your current position plus the desired size of the new position.)

Here is a sample system that shows how to do this: Indicator Based Stop and Reverse

You'll need to modify it slightly to take into account that you want to use a different indicator for the stop price depending on if the position is long or short, and also to always go long for the first position. Also note that you have to enable "Allow Position Reversal" in the paper trader settings for this to work.

Let us know if you have any problems.

Thanks,
Daniel
Posted Monday February 27 2012
Daniel, thanks.

I tried your Indicator Based Stop and Reverse system, but as you mentioned it always opens/closes the same position size and I'd like to dynamically change the position size based on my current equity.
Unfortunately, I couldn't create a script that reverse the position and defines the position size based on current equity, even modifying your example.

Can you, please show how can I reverse and get the size of a new position based on my current equity?

Thanks in advance

Edited: Monday February 27 2012 by alex_n
Posted Thursday March 08 2012
I've attached code for your system: Stop and reverse based on highest high and lowest low, with position size adjusting based on your account value each time a reversal occurs.

The main thing you need to do is calculate the desired position size based on the account value.  Here's the method which does this:

         long GetTargetPositionSize(double fillPrice)

         {

                 double amountToSpend = SystemData.AccountValue * PositionManager.Allocation / 100.0;

 

                 //       Simplified logic here will probably not work for all symbol types

                 double costPerUnit;

                 if (Symbol.SymbolInformation.Margin > 0)

                 {

                          costPerUnit = Symbol.SymbolInformation.Margin;

                 }

                 else

                 {

                          costPerUnit = fillPrice;

                 }

 

                 return (long)(amountToSpend / costPerUnit);

         }

Then, when submitting the stop and reverse order, instead of using twice the current position size, you use the current position size plus the desired position size:

stopSettings.Size = pos.CurrentSize + GetTargetPositionSize(stopSettings.StopPrice);

Hope this helps.

Thanks,
Daniel


Attachments
IndicatorStopAndReverse.cs (233 views, 3.00 KB)


Similar Topics


Reading This Topic


2005-2017 © RightEdge Systems