Пример #1
0
        public void Fill()
        {
            // market should fill on trade but not on quote
            OrderImpl o = new OrderImpl(security, Direction.Long, 100);

            Assert.True(o.Fill(TickImpl.NewTrade(security.Name, 9, 100), trans) == StatusType.ORDER_FILLED);
            Assert.True(o.Fill(TickImpl.NewBid(security.Name, 8, 100), trans) == StatusType.OK);

            // buy limit

            // limit should fill if order price is inside market
            o = new OrderImpl(security, Direction.Long, 100, 10m);
            Assert.True(o.Fill(TickImpl.NewTrade(security.Name, 9, 100), trans) == StatusType.ORDER_FILLED);
            // shouldn't fill outside market
            o = new OrderImpl(security, Direction.Long, 100, 10m);
            Assert.True(o.Fill(TickImpl.NewTrade(security.Name, 11, 100), trans) == StatusType.OK);

            // sell limit

            // limit should fill if order price is inside market
            o = new OrderImpl(security, Direction.Short, 100, 10m);
            Assert.True(o.Fill(TickImpl.NewTrade(security.Name, 11, 100), trans) == StatusType.ORDER_FILLED);
            // shouldn't fill outside market
            o = new OrderImpl(security, Direction.Short, 100, 10m);
            Assert.True(o.Fill(TickImpl.NewTrade(security.Name, 9, 100), trans) == StatusType.OK);

            // buy stop

            o = new OrderImpl(security, Direction.Long, 100, 0, 10m);
            Assert.True(o.Fill(TickImpl.NewTrade(security.Name, 11, 100), trans) == StatusType.ORDER_FILLED);
            // shouldn't fill outside market
            o = new OrderImpl(security, Direction.Long, 100, 0, 10m);
            Assert.True(o.Fill(TickImpl.NewTrade(security.Name, 9, 100), trans) == StatusType.OK);

            // sell stop

            o = new OrderImpl(security, Direction.Short, 100, 0, 10m);
            Assert.True(o.Fill(TickImpl.NewTrade(security.Name, 9, 100), trans) == StatusType.ORDER_FILLED);
            // shouldn't fill outside market
            o = new OrderImpl(security, Direction.Short, 100, 0, 10m);
            Assert.True(o.Fill(TickImpl.NewTrade(security.Name, 11, 100), trans) == StatusType.OK);

            // always fail filling an invalid tick
            o = new OrderImpl(security, Direction.Long, 100);
            Assert.False(o.Fill(TickImpl.NewTrade(security.Name, 0, 0), trans) == StatusType.ORDER_FILLED);

            // always fail filling invalid order
            o = new OrderImpl(security, Direction.Long, 100, 10);
            OrderImpl x = new OrderImpl();

            Assert.False(o.Fill(x) == StatusType.ORDER_FILLED);

            // always fail filling an order that doesn't cross market
            x = new OrderImpl(security, Direction.Long, 100);
            Assert.False(o.Fill(x) == StatusType.ORDER_FILLED);

            const string t2 = "agent2";

            // succeed on crossing market
            x             = new OrderImpl(security, Direction.Short, 100);
            x.AccountName = t2;
            Assert.True(o.Fill(x) == StatusType.ORDER_FILLED);

            // fail when accounts are the same
            x             = new OrderImpl(security, Direction.Short, 100);
            x.AccountName = o.AccountName;
            Assert.False(o.Fill(x) == StatusType.OK);

            // fail on match outside of market
            x             = new OrderImpl(security, Direction.Long, 100, 11);
            x.AccountName = t2;
            Assert.False(o.Fill(x) == StatusType.OK);

            // succeed on limit cross
            o             = new OrderImpl(security, Direction.Long, 100, 10);
            x             = new OrderImpl(security, Direction.Short, 100, 10);
            x.AccountName = t2;
            Assert.True(o.Fill(x) == StatusType.ORDER_FILLED);

            // make sure we can stop cross
            o             = new OrderImpl(security, Direction.Short, 100, 0, 10);
            x             = new OrderImpl(security, Direction.Long, 100);
            x.AccountName = t2;
            Assert.True(o.Fill(x) == StatusType.ORDER_FILLED);
        }
Пример #2
0
        /// <summary>
        /// Executes any open orders allowed by the specified tick.
        /// </summary>
        /// <param name="tick">The tick.</param>
        /// <returns>the number of orders executed using the tick.</returns>
        public int Execute(TickImpl tick)
        {
            //TODO: in order to calculate the floating PnL ticks are send to the account for calculations.
            //Also this location is incorrect!
            Default.OnTick(tick);
            BrokerCostCalculation(tick);
            if (_pendorders == 0)
            {
                return(0);
            }

            //Check if we need to process the order as a trade or use the bid ask fills
            UseBidAskFills = tick.HasAsk && tick.HasBid;

            int filledorders = 0;

            SimAccount[] accts = new SimAccount[MasterOrders.Count];
            MasterOrders.Keys.CopyTo(accts, 0);

            for (int idx = 0; idx < accts.Length; idx++)
            {
                // go through each account
                SimAccount a = accts[idx];

                // if account has requested no executions, skip it
                if (!a.Execute)
                {
                    continue;
                }
                //Check for a margin call by the broker
                if (a.MarginLevel <= BrokerModel.StopOutLevel())
                {
                    //cancel this order
                    MasterOrders[a].ForEach(x =>
                    {
                        ((PendingOrderImpl)x).OrderStatus = StatusType.INSUFFICIENT_CAPITAL;
                        x.Cancel();
                    });
                }

                // make sure we have a record for this account
                if (!MasterTrades.ContainsKey(a.Id))
                {
                    MasterTrades.Add(a.Id, new List <Trade>());
                }

                // track orders being removed and trades that need notification
                List <int> notifytrade = new List <int>();
                List <int> remove      = new List <int>();

                // go through each order in the account
                for (int i = 0; i < MasterOrders[a].Count; i++)
                {
                    //Get the order object
                    PendingOrderImpl po = (PendingOrderImpl)MasterOrders[a][i];
                    OrderImpl        o  = (OrderImpl)po.Order;

                    //make sure tick is for the right stock, and right exchange
                    if (tick.Symbol != o.Symbol)
                    {
                        continue;
                    }
                    //Check if order is in a correct state
                    if (po.OrderStatus != StatusType.OK)
                    {
                        remove.Add(i);
                        // count the trade
                        filledorders++;
                        continue;
                    }

                    if (UseHighLiquidityFillsEod)
                    {
                        po.OrderStatus = o.Fill(tick, BrokerModel, UseBidAskFills, false, true);
                    }
                    else if (o.ValidInstruct <= OrderInstructionType.GTC)
                    {
                        po.OrderStatus = o.Fill(tick, BrokerModel, UseBidAskFills, false); // fill our trade
                    }
                    else if (o.ValidInstruct == OrderInstructionType.OPG)
                    {
                        // if it's already opened, we missed our shot
                        if (_hasopened.Contains(o.Symbol))
                        {
                            continue;
                        }
                        // otherwise make sure it's really the opening
                        if (tick.Source == Opgex)
                        {
                            // it's the opening tick, so fill it as an opg
                            po.OrderStatus = o.Fill(tick, BrokerModel, UseBidAskFills, true);
                            // mark this symbol as already being open
                            _hasopened.Add(tick.Symbol);
                        }
                    }
                    // other orders fill normally, except MOC orders which are at 4:00PM
                    else if (o.ValidInstruct == OrderInstructionType.MOC)
                    {
                        if (tick.Time >= 160000000)
                        {
                            po.OrderStatus = o.Fill(tick, BrokerModel, UseBidAskFills, false); // fill our trade
                        }
                    }
                    else
                    {
                        po.OrderStatus = o.Fill(tick, BrokerModel, UseBidAskFills, false); // fill our trade
                    }
                    if (po.OrderStatus == StatusType.ORDER_FILLED)
                    {
                        // remove filled size from size available in trade
                        tick.Size -= o.UnsignedSize;

                        // get copy of trade for recording
                        TradeImpl trade = new TradeImpl(o);

                        // if trade represents entire requested order, mark order for removal
                        if (trade.UnsignedSize == o.UnsignedSize)
                        {
                            remove.Add(i);
                        }
                        else // otherwise reflect order's remaining size
                        {
                            o.Size = (o.UnsignedSize - trade.UnsignedSize) * (o.Direction == Direction.Long ? 1 : -1);
                        }

                        // record trade
                        MasterTrades[a.Id].Add(trade);

                        // mark it for notification
                        notifytrade.Add(MasterTrades[a.Id].Count - 1);

                        // count the trade
                        filledorders++;
                    }
                }

                // notify subscribers of trade
                if ((GotFill != null) && a.Notify)
                {
                    for (int tradeidx = 0; tradeidx < notifytrade.Count; tradeidx++)
                    {
                        TradeImpl t       = (TradeImpl)MasterTrades[a.Id][notifytrade[tradeidx]];
                        var       account = Acctlist[Accounts[0]];
                        t.Account     = account;
                        t.AccountName = t.Account.Id;
                        account.OnFill(t);
                        GotFill(t, MasterOrders[a][remove[tradeidx]]);
                    }
                }

                int rmcount = remove.Count;

                // remove the filled orders
                for (int i = remove.Count - 1; i >= 0; i--)
                {
                    MasterOrders[a].RemoveAt(remove[i]);
                }

                // unmark filled orders as pending
                _pendorders -= rmcount;
                if (_pendorders < 0)
                {
                    _pendorders = 0;
                }
            }
            return(filledorders);
        }