SmartQuant Discussion

Automated Quantitative Strategy Development, SmartQuant Product Discussion and Technical Support Forums
It is currently Mon Dec 09, 2024 12:16 am

All times are UTC + 3 hours




Post new topic Reply to topic  [ 11 posts ] 
Author Message
PostPosted: Wed Mar 21, 2007 1:58 pm 
Offline

Joined: Tue Aug 05, 2003 3:43 pm
Posts: 6817
The following moving average crossover strategy ships with the OpenQuant system, and uses moving average crossovers to enter trades. This strategy (like the breakout strategy shown above) has three methods for exiting a trade. It can use the moving averages, the OCA One Cancels All method, or a trailing stop indicator method (which initiates a market order to close the position). Notice the use of a trailing stop indicator, rather than a stop order, to exit the trade. The stop is just a stop that is maintained by the strategy framework (not the broker). The trailing stop fires when an incoming trade price reaches the stop limit, and the OnStopExecuted event handler is called. The event handler issues a market order to close the position. This way, no stop order is ever issued to the broker (perhaps some brokers or exchanges don’t take trailing stops).

Code:
using System;
using System.Drawing;

using OpenQuant.API;
using OpenQuant.API.Indicators;

public class MyStrategy : Strategy
{
   [Parameter("Length of SMA1", "SMA")]
   int Length1 = 3;

   [Parameter("Length of SMA2", "SMA")]
   int Length2 = 7;

   [Parameter("Color of SMA1", "SMA")]
   Color Color1 = Color.Yellow;   

   [Parameter("Color of SMA2", "SMA")]
   Color Color2 = Color.LightBlue;
   
   [Parameter("Stop OCA Level", "OCA")]
   double StopOCALevel = 0.98;

   [Parameter("Limit OCA Level", "OCA")]
   double LimitOCALevel = 1.05;
   
   [Parameter("Stop Level", "Stop")]
   double StopLevel = 0.05;

   [Parameter("Stop Type", "Stop")]
   StopType StopType = StopType.Trailing;
   
   [Parameter("StopMode", "Stop")]
   StopMode StopMode = StopMode.Percent;
   
   [Parameter("CrossoverExitEnabled", "Exit")]
   bool CrossoverExitEnabled = true;
   
   [Parameter("OCA Exit Enabled", "Exit")]
   bool OCAExitEnabled = true;

   [Parameter("Stop Exit Enabled", "Exit")]
   bool StopExitEnabled = true;
   
   // this strategy uses some of the same exit methods
   // as the breakout strategy described earlier. Look
   // there for additional documentation
   // lengths and colors of the simple moving averages   
   SMA sma1;
   SMA sma2;

   // only one trade is allowed at a time
   bool entryEnabled = true;   
   
   int OCACount = 0;

   // for the orders used by this strategy
   Order marketOrder,
      limitOrder,
      stopOrder;

   [Parameter("Order quantity (number of contracts to trade)")]
   double Qty = 100;

   public override void OnStrategyStart()
   {
      // set up the moving averages, based on closing prices
      sma1 = new SMA(Bars, Length1, Color1);
      sma2 = new SMA(Bars, Length2, Color2);
      // 0 means draw both averages on the price chart
      Draw(sma1, 0);
      Draw(sma2, 0);
   }

   public override void OnBar(Bar bar)
   {
      // does the fast average cross over the slow average?
      // if so, time to buy long
      Cross cross = sma1.Crosses(sma2, bar);
      // we only allow one active position at a time
      if (entryEnabled)
      {
         // if price trend is moving upward, open a long
         // position using a market order, and send it in
         if (cross == Cross.Above)
         {
            marketOrder = MarketOrder(OrderSide.Buy, Qty, "Entry");            
            marketOrder.Send();
            // if one cancels all exit method is desired, we
            // also issue a limit (profit target) order, and
            // a stop loss order in case the breakout fails.
            // The OCA exit method uses a real stop loss order.
            // The Stop exit method uses a stop indicator.
            // Use either the OCA or Stop method, not both at once.
            if (OCAExitEnabled)
            {
               // create and send a profit limit order
               double profitTarget = LimitOCALevel * bar.Close;
               limitOrder = SellLimitOrder(Qty, profitTarget, "Limit OCA " + OCACount);
               limitOrder.OCAGroup = "OCA " + Instrument.Symbol + " "
                  + OCACount;               
               limitOrder.Send();
               // create and send a stop loss order
               double lossTarget = StopOCALevel * bar.Close;
               stopOrder = SellStopOrder(Qty, lossTarget, "Stop OCA " + OCACount);
               stopOrder.OCAGroup = "OCA " + Instrument.Symbol + " "
                  + OCACount;               
               stopOrder.Send();
               // bump the OCA count to make OCA group strings unique
               OCACount++;
            }
            entryEnabled = false;
         }
      }
         // else if entry is disabled on this bar, we have an open position
      else
      {
         // if we are using the crossover exit, and if the fast
         // average just crossed below the slow average, issue a
         // market order to close the existing position
         if (CrossoverExitEnabled)
            if (cross == Cross.Below)
            {
               marketOrder = MarketOrder(OrderSide.Sell, Qty, "Crossover Exit");               
               marketOrder.Send();
            }
      }
   }
   public override void OnPositionOpened()
   {
      // if we want to exit trades using the Stop method, set a
      // a trailing stop indicator when the position is
      // first opened. The stop indicator is not a stop loss
      // order that can be executed by a broker. Instead, the stop
      // just fires the OnStopExecuted event when it it triggered.
      if (StopExitEnabled)
         SetStop(StopLevel, StopType, StopMode);
   }

   public override void OnPositionClosed()
   {
      // when a position is closed, cancel the limit and stop
      // orders that might be associated with this position.
      // But only cancel if the order has not been filled or
      // not been cancelled already.
      if (OCAExitEnabled &&
         !(limitOrder.IsFilled || limitOrder.IsCancelled))
      {
         limitOrder.Cancel();
      }
      // allow entries once again, since our position is closed
      entryEnabled = true;
   }

   public override void OnStopExecuted(Stop stop)
   {
      // if our trailing stop indicator was executed,
      // issue a market sell order to close the position.
      marketOrder = MarketOrder(OrderSide.Sell, Qty, "Stop Exit");      
      marketOrder.Send();
   }
}



Top
 Profile  
 
PostPosted: Tue Dec 18, 2007 11:09 pm 
Offline

Joined: Tue Dec 18, 2007 10:06 pm
Posts: 9
Hi Anton,

-Instead of having slow and fast moving averages to cross, is it possible to set price cross both moving averages? Something like price.close>SMA(20).value.

-Is it possible to have the strategy check weekly SMA and then process daily SMA. Some sort of functional dependency. This means if price.close>SMA(20).value for weekly && price.close>SMA(20).value for daily, then buy(quantity).

Regards,

_________________
Sasha


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 19, 2007 6:20 pm 
Offline

Joined: Tue Aug 05, 2003 3:43 pm
Posts: 6817
Hi,

why not.

It would look like

Code:
public override void OnBar(Bar bar)
{
  if (bar.Close > sma.Last)
    Buy(qty);
}


You can also have two sma, one taking daily series as input and the other one taking weekly series (or 1min and 5min series for example). We will publish an example on this in the FAQ section soon.

Regards,
Anton


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 30, 2009 11:24 pm 
Offline

Joined: Wed Jan 09, 2008 12:19 pm
Posts: 49
Hi,

OnPositionClosed() doesn't seem to work when I have both long and short entry logic on strategy.

Let's say if I am in short position with limit orders (stop loss and target),It should cancel current limit orders when I get filled for next long position. But this logic keeps on adding long/short limit orders without cancelling previous ones.
Does this logic should work on both long and short entries ?
Could anyone help me on this issue ?

Thanks.

public override void OnPositionClosed()
{
// when a position is closed, cancel the limit and stop
// orders that might be associated with this position.
// But only cancel if the order has not been filled or
// not been cancelled already.
if (OCAExitEnabled &&
!(limitOrder.IsFilled || limitOrder.IsCancelled))
{
limitOrder.Cancel();
}
// allow entries once again, since our position is closed
entryEnabled = true;
}


Last edited by octrout on Thu Jul 02, 2009 5:38 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 01, 2009 3:59 pm 
Offline

Joined: Wed Oct 08, 2003 1:06 pm
Posts: 833
Hi,

Is it true that you don't close your short postitions but reverse them to long positions?

If yes then the OnPositionClosed handler doesn't get called, in this case you should use OnPositionChanged instead, together with some flag telling you that you should cancel active orders as a reaction on reversing your position to long.

Regards,
Sergey.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 01, 2009 5:10 pm 
Offline

Joined: Wed Jan 09, 2008 12:19 pm
Posts: 49
No. It closed my short position.
But it doesn't cancel the limit orders which were sent along with market orders.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 01, 2009 5:22 pm 
Offline

Joined: Wed Oct 08, 2003 1:06 pm
Posts: 833
You can try to override OnOrderFilled(Order order) handler and calcell your limit and stop orders in it if the "order" parameters is not one of the active limit and stop orders.

smth like:
public override void OnOrderFilled(Order order)
{
if (order != stopOrder && order != limitOrder)
{
if (OCAExitEnabled &&
!(limitOrder.IsFilled || limitOrder.IsCancelled))
{
limitOrder.Cancel();
}
// allow entries once again, since our position is closed
entryEnabled = true;
}
}
}


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 01, 2009 5:38 pm 
Offline

Joined: Wed Jan 09, 2008 12:19 pm
Posts: 49
Hi,

I just used your logic but it gets cancelled as soon as my marketOrder get filled.
Thanks.

Quote:
public override void OnOrderFilled(Order order)
{
if (order != stopOrder && order != limitOrder)
{
if (OCAExitEnabled &&
!(limitOrder.IsFilled || limitOrder.IsCancelled))
{
limitOrder.Cancel();
}
// allow entries once again, since our position is closed
entryEnabled = true;
}
}
}


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 02, 2009 12:57 pm 
Offline

Joined: Wed Oct 08, 2003 1:06 pm
Posts: 833
Hi,

I thought this is what you are trying to achieve - your strategy sends market orders to open/reverse positions and stop loss and take profit orders shoud be calcelled as soon as you send a market order gets filled.

Or you want to do something else?

Regards,
Sergey.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 02, 2009 5:47 pm 
Offline

Joined: Wed Jan 09, 2008 12:19 pm
Posts: 49
Yes. But my limit order and stop order get cancelled as soon as it sends market order.
My limit order and stop order should stay until I get reverse position.
For example, As soon as I get filled long entry, it also shows as cancelled stop and limit order in order Manager.


Top
 Profile  
 
PostPosted: Thu Aug 28, 2014 4:39 pm 
Offline

Joined: Mon Jul 28, 2014 2:18 pm
Posts: 1
I guess this is not going to work for every pair. You at least need some kind of pre functioned data to jump into the market.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 11 posts ] 

All times are UTC + 3 hours


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group