NexusFi: Find Your Edge


Home Menu

 





Auto trading CL futures with Ninja and IB


Discussion in NinjaTrader

Updated
      Top Posters
    1. looks_one sam028 with 5 posts (1 thanks)
    2. looks_two goforbroke01 with 3 posts (0 thanks)
    3. looks_3 Fat Tails with 3 posts (6 thanks)
    4. looks_4 fle__ with 2 posts (4 thanks)
    1. trending_up 15,658 views
    2. thumb_up 11 thanks given
    3. group 10 followers
    1. forum 22 posts
    2. attach_file 0 attachments




 
Search this Thread

Auto trading CL futures with Ninja and IB

  #1 (permalink)
 goforbroke01 
Chicago
 
Experience: Intermediate
Platform: NT
Broker: IB
Posts: 11 since Jun 2009
Thanks Given: 8
Thanks Received: 1

I've been manually trading with a very simple strategy and I converted it to trade automatically with NT and Interactive Brokers. That's when my problems started (apart from making money!). I posted on the NT forum: [COLOR=blue][FONT=&quot]Automated strategy with [AUTOLINK]Interactive Brokers[/AUTOLINK] and CL - Page 2 - [AUTOLINK]NinjaTrader[/AUTOLINK] Support Forum[/FONT][/COLOR] and ended up at a dead end. Basically, when sending an order to IB for an energy future, where the contract expires during the month before the contract month, IB fills the order correctly and NT interprets the IB order execution and position messages as if an order had been filled for the prior month contract. As a result the strategy thinks it's flat, the chart is not updated and no strategy issued stop orders are acted upon.

Between NT and IB they have failed to fix this since at least April of this year and neither party can give me any idea of when it might be. So if I want to trade in this way I have to use an alternative to NT (with which I have, as have many, invested a massive amount of time) or change my broker.

The purpose of bringing this all up here is to see if anyone else has suffered this, and if so, how they got around it. It seems to me that the combination of NT auto strategy, IB and energy futures are not compatible. Are there any workarounds out there?

-thanks

Started this thread Reply With Quote

Can you help answer these questions
from other members on NexusFi?
Online prop firm The Funded Trader (TFT) going under?
Traders Hideout
Better Renko Gaps
The Elite Circle
Build trailing stop for micro index(s)
Psychology and Money Management
Are there any eval firms that allow you to sink to your …
Traders Hideout
Exit Strategy
NinjaTrader
 
Best Threads (Most Thanked)
in the last 7 days on NexusFi
Get funded firms 2023/2024 - Any recommendations or word …
56 thanks
Funded Trader platforms
44 thanks
NexusFi site changelog and issues/problem reporting
24 thanks
GFIs1 1 DAX trade per day journal
22 thanks
The Program
19 thanks
  #2 (permalink)
 
sam028's Avatar
 sam028 
Site Moderator
 
Posts: 3,765 since Jun 2009
Thanks Given: 3,825
Thanks Received: 4,629

An interesting post about this issue, here.
If your entries/exit are simple, no scale-in/out, etc, there is maybe a solution...

Follow me on Twitter Reply With Quote
  #3 (permalink)
 goforbroke01 
Chicago
 
Experience: Intermediate
Platform: NT
Broker: IB
Posts: 11 since Jun 2009
Thanks Given: 8
Thanks Received: 1


Sam028

Thanks for the reply. I have previously reviewed that thread and tried downgrading to TWS890 that was reported by a user as working. It didn't work and IB subsequently told me: "Unfortunately, the related change is within our server side. It is not feasible to fix this issue by downgrading to the 890 version of TWS. We have to provide a new API component in order to fix the issue."

Is this what you were referring to when you said there may be a solution?

-thanks

Started this thread Reply With Quote
  #4 (permalink)
 
sam028's Avatar
 sam028 
Site Moderator
 
Posts: 3,765 since Jun 2009
Thanks Given: 3,825
Thanks Received: 4,629


goforbroke01 View Post
Sam028

Thanks for the reply. I have previously reviewed that thread and tried downgrading to TWS890 that was reported by a user as working. It didn't work and IB subsequently told me: "Unfortunately, the related change is within our server side. It is not feasible to fix this issue by downgrading to the 890 version of TWS. We have to provide a new API component in order to fix the issue."

Is this what you were referring to when you said there may be a solution?

-thanks

No. I think the solution might be something like:
- the strat is running with the simulation account, then:
-> a small program wrote in Java/C++ with the TWS API libraries read every x seconds the NT Access database, then send the order with the right contract to the TWS. I have a piece of Java code somewhere, which were doing something similar
or, maybe simple (and simple==reliable)
-> the strategy wrote in a text file what to do, then another simple Java/C++ (always with the TWS API lib) read this file every second, then send the real order to TWS.

But all these will only works with simple order management/simple money management, because NT will be lost, its position will be false, the truth will be in TWS only.

I'm testing this bug right now with TWS demo account and a basic strat, scary...

Follow me on Twitter Reply With Quote
  #5 (permalink)
 goforbroke01 
Chicago
 
Experience: Intermediate
Platform: NT
Broker: IB
Posts: 11 since Jun 2009
Thanks Given: 8
Thanks Received: 1

Got it. Run NT and TWS separately with NT putting order information in a text file and a standalone program polling it and posting orders through the TWS API. I am an amateur programmer and will give it a try, maybe in C#. I will report back if I get it to work. I would welcome if you could share any of your success and/or challenges along the way. Thanks for your help.

-thanks

Started this thread Reply With Quote
  #6 (permalink)
 
sam028's Avatar
 sam028 
Site Moderator
 
Posts: 3,765 since Jun 2009
Thanks Given: 3,825
Thanks Received: 4,629

Writing a basic text file within a strategy is quite easy in C#, there is an example in the official NT forum, here.
For reading this file, you can also have a look to trading-shim, which is made to talk with a TWS, and can read "orders" files. But I only played with it on Linux boxes, I'm not sure it can be run safely under Windows.
Anyway, the "reader" part might not be very hard to write in Java, there is some examples on how to use the TWS API, after reading the text file, it's something like:
 
Code
                            
...
            if (
contract_type.equals("FUT")){                
                
contract createContract(symbolcontract_typeexchange"USD");
            }
...                
            if (
order_type.equals("MKT"))
                
my_order createOrder(actionqty"MKT");
            if ( (
order_type.equals("LMT")) && (limit>0))
                
my_order createOrder(actionqty"LMT",limit);
....            
            
eClientSocket.placeOrder(ORDERIDcontractmy_order);
.... 

Follow me on Twitter Reply With Quote
Thanked by:
  #7 (permalink)
fle__
Paris / France
 
Posts: 21 since Sep 2009
Thanks Given: 2
Thanks Received: 10

Hi,
have a look at this : Interactive Brokers C# Api | Dinosaur Technology and Trading
the c# could be the basis of your polling app, and there is only one programming language for your whole trading system. Its simpler.
Nt exports all executions in the "outgoing" directory, I remember that two files were involved. You will have to check yourself.

But there is more :
you can import all this interface source code to NT, compile, and run it directly from NT (from within a strat or an indic). You would place your code in the Onexecution().

Have fun.

Reply With Quote
Thanked by:
  #8 (permalink)
 
sam028's Avatar
 sam028 
Site Moderator
 
Posts: 3,765 since Jun 2009
Thanks Given: 3,825
Thanks Received: 4,629


fle__ View Post
Hi,
have a look at this : Interactive Brokers C# Api | Dinosaur Technology and Trading
the c# could be the basis of your polling app, and there is only one programming language for your whole trading system. Its simpler.
Nt exports all executions in the "outgoing" directory, I remember that two files were involved. You will have to check yourself.

But there is more :
you can import all this interface source code to NT, compile, and run it directly from NT (from within a strat or an indic). You would place your code in the Onexecution().

Have fun.

Wow, great link, powerful things can be done with this, without too much headaches. And not only for solving CL contract dates issue.
A strategy which is hedging stock trades with options looks possible now, and using IB combos, etc.

Follow me on Twitter Reply With Quote
  #9 (permalink)
fle__
Paris / France
 
Posts: 21 since Sep 2009
Thanks Given: 2
Thanks Received: 10

I can't export the strategy, so I just past the code :
I works on ES 1209

It has a problem : the system is SAR, so always in the market. If you don't match manually the strategy starting position with the account position, it does not work, because the first order of the strategy closes the current position (which does not exist if not entered manually) and then opens a new position in the opposite direction. Non SAR does not have this problem by starting the strategy when it is flat.

 
Code
// 
// Copyright (C) 2006, NinjaTrader LLC <www.ninjatrader.com>.
// NinjaTrader reserves the right to modify or overwrite this NinjaScript component with each release.
//

#region Using declarations
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Xml.Serialization;
using NinjaTrader.Cbi;
using NinjaTrader.Data;
using NinjaTrader.Indicator;
using NinjaTrader.Strategy;
using System.Collections.Generic;
using System.Text;
using Krs.Ats.IBNet;
using System.Threading;
using Krs.Ats.IBNet.Contracts;

#endregion

// This namespace holds all strategies and is required. Do not change it.
namespace NinjaTrader.Strategy
{
    /// <summary>
    /// Simple moving average cross over strategy.
    /// </summary>
    [Description("Simple moving average cross over strategy.")]
    public class _SampleIBinterface : Strategy
    {
        #region Variables
        private int        fast    = 5;
        private int        slow    = 10;
        
        private IOrder entryOrder = null;
        private static int NextOrderId = 0;
        private static Contract ES;
        private static Contract NQ;
        private static IBClient client;

        #endregion

        /// <summary>
        /// This method is used to configure the strategy and is called once before any strategy method is called.
        /// </summary>
        protected override void Initialize()
        {
            client = new IBClient();
            client.ThrowExceptions = true;

            client.TickPrice += client_TickPrice;
            client.TickSize += client_TickSize;
            client.Error += client_Error;
            client.NextValidId += client_NextValidId;
            client.UpdateMarketDepth += client_UpdateMktDepth;
            client.RealTimeBar += client_RealTimeBar;
            client.OrderStatus += client_OrderStatus;
            client.ExecDetails += new EventHandler<ExecDetailsEventArgs>(client_ExecDetails);
            ES = new Contract("ES", "GLOBEX", SecurityType.Future, "USD", "200912");

            
            SMA(Fast).Plots[0].Pen.Color = Color.Orange;
            SMA(Slow).Plots[0].Pen.Color = Color.Green;

            Add(SMA(Fast));
            Add(SMA(Slow));

            CalculateOnBarClose    = true;
        }

        /// <summary>
        /// Called on each bar update event (incoming tick).
        /// </summary>
        protected override void OnBarUpdate()
        {
            if (!client.Connected && !Historical) 
            {
                Print("Connecting to IB.");
                Trace.WriteLine("Connecting to IB.");
                client.Connect("127.0.0.1", 7496, ToTime(Time[0]));
            }
            else if(!Historical)
            {
                Print("Connected to IB.");
            }

            if (CrossAbove(SMA(Fast), SMA(Slow), 1))
                entryOrder = EnterLong();
            else if (CrossBelow(SMA(Fast), SMA(Slow), 1))
                entryOrder = EnterShort();
            
            if (entryOrder != null &&!Historical) Print("OnBarUpdate entryOrder "+entryOrder.ToString());
        }

        protected override void OnOrderUpdate(IOrder order)
        {
            if (entryOrder != null) Print("OnOrderUpdate Order "+entryOrder.ToString());
            else Print("OnOrderUpdate Order Nill");
            // Handle entry orders here. The entryOrder object allows us to identify that the order that is calling the OnOrderUpdate() method is the entry order.
            if (entryOrder != null && entryOrder.Token == order.Token)
            {    
                // Reset the entryOrder object to null if order was cancelled without any fill
                if (order.OrderState == NinjaTrader.Cbi.OrderState.Cancelled && order.Filled == 0)
                {
                    entryOrder = null;
                }
            }
        }

        
        protected override void OnExecution(IExecution execution) 
        { 
            Print("OnExecution Exec "+execution.ToString());

            if ((entryOrder != null && entryOrder.Token == execution.Order.Token) || execution.Order.Name == "Close position")
            {
                if (!Historical) 
                {
                    if (execution.Order.OrderState == NinjaTrader.Cbi.OrderState.Filled 
                        || execution.Order.OrderState == NinjaTrader.Cbi.OrderState.PartFilled 
                        || (execution.Order.OrderState == NinjaTrader.Cbi.OrderState.Cancelled && execution.Order.Filled > 0))
                    {
                        Krs.Ats.IBNet.Order TradedContractOrder = new Krs.Ats.IBNet.Order();
                        if (execution.MarketPosition==MarketPosition.Long)
                            TradedContractOrder.Action = ActionSide.Buy;
                        else
                            TradedContractOrder.Action = ActionSide.Sell;
                        TradedContractOrder.OutsideRth = false;
                        TradedContractOrder.OrderType = Krs.Ats.IBNet.OrderType.Market;
                        TradedContractOrder.TotalQuantity = execution.Quantity;
                        DateTime myTime = new DateTime();
                        myTime = DateTime.Now;
                        NextOrderId++;
                        client.PlaceOrder(NextOrderId, ES, TradedContractOrder);
                        
    //                    client.PlaceOrder(Convert.ToInt32(execution.Token), ES, TradedContractOrder);
                        Log("Exec "+execution.ToString(), NinjaTrader.Cbi.LogLevel.Information );
                        entryOrder     = null;
                    }
                
                    Print("OnExecution "+execution.ToString());
                }
            }
        }
        
        public override void Dispose() 
        { 
            // Clean up your resources here 
            // WILL BE A PROBLEM IF TWO CHART HAVE THE INDICATOR
                client.Disconnect();
                client.Dispose();
                Print("Disposing IB interface");            
            base.Dispose(); 
        }
        
        static void client_ExecDetails(object sender, ExecDetailsEventArgs e)
        {
            Console.WriteLine("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11}",
                e.Contract.Symbol, e.Execution.AccountNumber, e.Execution.ClientId, e.Execution.Exchange, e.Execution.ExecutionId,
                e.Execution.Liquidation, e.Execution.OrderId, e.Execution.PermId, e.Execution.Price, e.Execution.Shares, e.Execution.Side, e.Execution.Time);

            Console.WriteLine("IBExecDetails "+e.ToString());
        }

        static void client_RealTimeBar(object sender, RealTimeBarEventArgs e)
        {
            Console.WriteLine("Received Real Time Bar: " + e.Close);
            Trace.WriteLine("Received Real Time Bar: " + e.Close);
        }

        static void client_OrderStatus(object sender, Krs.Ats.IBNet.OrderStatusEventArgs e)
        {
            Console.WriteLine("Order Placed.");
            Console.WriteLine("Order Status"+e.ToString());
//            if (e.Status == OrderStatus.Canceled && order.Filled == 0)
//                {
//                    entryOrder = null;
//                }
        }

        static void client_UpdateMktDepth(object sender, UpdateMarketDepthEventArgs e)
        {
            Console.WriteLine("Tick ID: " + e.TickerId + " Tick Side: " + EnumDescConverter.GetEnumDescription(e.Side) +
                              " Tick Size: " + e.Size + " Tick Price: " + e.Price + " Tick Position: " + e.Position +
                              " Operation: " + EnumDescConverter.GetEnumDescription(e.Operation));
            Trace.WriteLine("Tick ID: " + e.TickerId + " Tick Side: " + EnumDescConverter.GetEnumDescription(e.Side) +
                              " Tick Size: " + e.Size + " Tick Price: " + e.Price + " Tick Position: " + e.Position +
                              " Operation: " + EnumDescConverter.GetEnumDescription(e.Operation));
        }

        static void client_NextValidId(object sender, NextValidIdEventArgs e)
        {
            Console.WriteLine("Next Valid Id: " + e.OrderId);
            NextOrderId = e.OrderId;
        }

        static void client_TickSize(object sender, TickSizeEventArgs e)
        {
            Console.WriteLine("Tick Size: " + e.Size + " Tick Type: " + EnumDescConverter.GetEnumDescription(e.TickType));
        }

        static void client_Error(object sender, ErrorEventArgs e)
        {
            Console.WriteLine("Error: "+ e.ErrorMsg);
            Trace.WriteLine("Error: "+ e.TickerId+ " "+ e.ErrorCode+ " "+ e.ErrorMsg);
        }

        static void client_TickPrice(object sender, TickPriceEventArgs e)
        {
            Console.WriteLine("Price: " + e.Price + " Tick Type: " + EnumDescConverter.GetEnumDescription(e.TickType));
        }


        #region Properties
        /// <summary>
        /// </summary>
        [Description("Period for fast MA")]
        [Category("Parameters")]
        public int Fast
        {
            get { return fast; }
            set { fast = Math.Max(1, value); }
        }

        /// <summary>
        /// </summary>
        [Description("Period for slow MA")]
        [Category("Parameters")]
        public int Slow
        {
            get { return slow; }
            set { slow = Math.Max(1, value); }
        }
        #endregion
    }
}

Reply With Quote
Thanked by:
  #10 (permalink)
evroom1
sarasota fl
 
Posts: 42 since Dec 2009
Thanks Given: 31
Thanks Received: 15


Dec 17 2009 I also have this same problem. I was doing fine then bang no stops entered. Ninja nor IB have of this date fixed the the problem. Has anyone ever recieved a notice from either IB or ninja that this might happen? I am looking for a credit since this is a known problem. Any one ever got a credit on this type of thing?

Reply With Quote




Last Updated on October 29, 2010


© 2024 NexusFi™, s.a., All Rights Reserved.
Av Ricardo J. Alfaro, Century Tower, Panama City, Panama, Ph: +507 833-9432 (Panama and Intl), +1 888-312-3001 (USA and Canada)
All information is for educational use only and is not investment advice. There is a substantial risk of loss in trading commodity futures, stocks, options and foreign exchange products. Past performance is not indicative of future results.
About Us - Contact Us - Site Rules, Acceptable Use, and Terms and Conditions - Privacy Policy - Downloads - Top
no new posts