예제 #1
0
 public Trade(Trade copy)
 {
     Id = copy.Id;
     FullSymbol = copy.FullSymbol;
     Account = copy.Account;
     TradeDate = copy.TradeDate;
     TradeTime = copy.TradeTime;
     TradePrice = copy.TradePrice;
     TradeSize = copy.TradeSize;
 }
예제 #2
0
        public static Trade Deserialize(string tstr)
        {
            string[] ts = tstr.Split(',');
            if (ts.Length < 14) throw new Exception("Invalid trade");

            Trade t = new Trade();
            t.Id = Convert.ToInt64(ts[0], System.Globalization.CultureInfo.InvariantCulture);
            t.Account = ts[1];
            t.TradeDate = Convert.ToInt32(ts[2], System.Globalization.CultureInfo.InvariantCulture);
            t.TradeTime = Convert.ToInt32(ts[3], System.Globalization.CultureInfo.InvariantCulture);
            t.FullSymbol = ts[4];
            t.TradeSize = Convert.ToInt32(ts[5], System.Globalization.CultureInfo.InvariantCulture);
            t.TradePrice = Convert.ToDecimal(ts[6], System.Globalization.CultureInfo.InvariantCulture);

            return t;
        }
예제 #3
0
 public decimal Adjust(Trade t)
 {
     return Adjust(new Position(t)); 
 }
예제 #4
0
 /// <summary>
 /// Gets the closed PL on a position basis, the PL that is registered to the account for the entire shares transacted.
 /// </summary>
 /// <param name="existing">The existing position.</param>
 /// <param name="closing">The portion of the position being changed/closed.</param>
 /// <returns></returns>
 public static decimal ClosePL(Position existing, Trade adjust)
 {
     int closedsize = Math.Abs(adjust.TradeSize) > existing.UnsignedSize ? existing.UnsignedSize : Math.Abs(adjust.TradeSize);
     return ClosePT(existing, adjust) * closedsize * Security.GetMultiplierFromFullSymbol(adjust.FullSymbol);
 }
예제 #5
0
 public override void GotFill(Trade f)
 {
     Adjust(new Position(f));
 }
예제 #6
0
 public void GotFill(Trade f) { Adjust(f); }
예제 #7
0
        void _backtestengine_GotFillEvent(Trade t)
        {
            _tradelist.Add(t);

            Position mypos = new Position(t);
            decimal closepnl = 0;
            decimal closepoint = 0;
            if (!_positionlist.TryGetValue(t.FullSymbol, out mypos))
            {
                mypos = new Position(t);
                _positionlist.Add(t.FullSymbol, mypos);
            }
            else
            {
                closepoint = Calc.ClosePT(mypos, t);
                closepnl = mypos.Adjust(t);
                _positionlist[t.FullSymbol] = mypos;
            }

            System.Windows.Application.Current.Dispatcher.Invoke(() =>
            {
                _positiontable.Rows.Add(t.TradeTime.ToString(), mypos.FullSymbol, mypos.Size, mypos.AvgPrice.ToString(_dps), closepnl.ToString("C2"), closepoint.ToString(_dps));
                _filltable.Rows.Add(t.TradeTime.ToString(), t.FullSymbol, t.TradeSize, t.TradePrice.ToString(_dps), t.Id);
            });
        }
예제 #8
0
        public static string Serialize(Trade t)
        {
            string[] trade = new string[] { 
                t.Id.ToString(System.Globalization.CultureInfo.InvariantCulture),
                t.Account,
                t.TradeDate.ToString(System.Globalization.CultureInfo.InvariantCulture), 
                t.TradeTime.ToString(System.Globalization.CultureInfo.InvariantCulture), 
                t.FullSymbol, 
                t.TradeSize.ToString(System.Globalization.CultureInfo.InvariantCulture), 
                t.TradePrice.ToString("F2", System.Globalization.CultureInfo.InvariantCulture), 
            };

            return string.Join(",", trade);
        }
 private decimal CalculateIBCommissions(Trade t)
 {
     if (t.FullSymbol.Contains("STK"))
     {
         return (decimal)Math.Max(0.005 * Math.Abs(t.TradeSize), 1);
     }
     else if (t.FullSymbol.Contains("FUT"))
     {
         return 2.01m * Math.Abs(t.TradeSize);
     }
     else if (t.FullSymbol.Contains("OPT"))
     {
         return Math.Max(0.70m * Math.Abs(t.TradeSize), 1);
     }
     else if (t.FullSymbol.Contains("CASH"))
     {
         return Math.Max(0.000002m * (t.TradePrice * t.TradeSize), 2);
     }
     else
     {
         return 0;
     }
 }
예제 #10
0
 private void OnGotFill(Trade t)
 {
     var handler = GotFillHandler;
     if (handler != null) handler(t);
 }
예제 #11
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(Tick tick)
        {
            if (_pendingorders == 0) return 0;
            if (!tick.IsTrade && !_usebidaskfill) return 0;
            int filledorders = 0;
            Account[] accts = new Account[_masterorders.Count];
            _masterorders.Keys.CopyTo(accts, 0);

            // go through each account
            for (int idx = 0; idx < accts.Length; idx++)
            { 
                Account a = accts[idx];
                // if account has requested no executions, skip it
                if (!a.Execute) continue;
                // 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++)
                {
                    Order o = _masterorders[a][i];
                    //make sure tick is for the right stock
                    if (tick.FullSymbol != o.FullSymbol)
                        continue;
                    bool filled = false;
                    if (UseHighLiquidityFillsEOD)
                    {
                        Order oi = (Order)o;
                        filled = oi.FillHighLiquidityEOD(tick, _usebidaskfill, false);
                    }
                    else if (o.TIF <= TimeInForce.GTC)
                    {
                        filled = o.Fill(tick, _usebidaskfill, false); // fill our trade
                    }
                    else if (o.TIF == TimeInForce.OPG)
                    {
                        // if it's already opened, we missed our shot
                        if (_hasopened.Contains(o.FullSymbol))
                            continue;
                        // otherwise make sure it's really the opening
                        //if (tick.Exchange == OPGEX)
                        {
                            // it's the opening tick, so fill it as an opg
                            filled = o.Fill(tick, _usebidaskfill, true);
                            // mark this symbol as already being open
                            _hasopened.Add(tick.FullSymbol);
                        }

                    }
                    // other orders fill normally, except MOC orders which are at 4:00PM
                    else if (o.TIF == TimeInForce.MOC)
                    {
                        if (tick.Time >= 160000)
                            filled = o.Fill(tick, _usebidaskfill, false); // fill our trade
                    }
                    else
                        filled = o.Fill(tick, _usebidaskfill, false); // fill our trade

                    if (filled)
                    {
                        // get copy of trade for recording
                        Trade trade = new Trade((Trade)o);
                        
                        // remove filled size from size available in trade
                        if (_adjustincomingticksize)
                        {
                            if (_usebidaskfill)
                            {
                                if (o.Side)
                                    tick.AskSize -= trade.UnsignedSize;
                                else
                                    tick.BidSize -= trade.UnsignedSize;
                            }
                            else
                                tick.TradeSize -= trade.UnsignedSize;
                        }
                        
                        // 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.OrderSize = (o.UnsignedSize - trade.UnsignedSize) * (o.OrderSide ? 1 : -1);

                        // record trade
                        _mastertrades[a.ID].Add(trade);
                        // mark it for notification
                        notifytrade.Add(_mastertrades[a.ID].Count - 1);
                        // count the trade
                        filledorders++;
                    }
                }
                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
                _pendingorders -= rmcount;
                if (_pendingorders < 0) _pendingorders = 0;
                // notify subscribers of trade
                if (a.Notify)
                    for (int tradeidx = 0; tradeidx < notifytrade.Count; tradeidx++)
                        OnGotFill(_mastertrades[a.ID][notifytrade[tradeidx]]);

            }
            return filledorders;
        }
예제 #12
0
 public Position(Trade t) 
 {
     if (!t.IsValid) throw new Exception("Can't construct a position object from invalid trade.");
     _fullsymbol = t.FullSymbol; _avgprice = t.TradePrice; _size = t.TradeSize; _date = t.TradeDate; _time = t.TradeTime; _acct = t.Account;
     if (_size>0) _size *= t.Side ? 1 : -1;
 }
예제 #13
0
 /// <summary>
 /// Called when orders are filled as trades.
 /// track or respond to trades here, eg:
 /// positionTracker.Adjust(fill);
 /// </summary>
 /// <param name="fill"></param>
 public virtual void GotFill(Trade f)
 {
 }
예제 #14
0
        public void GotFill(Trade f)
        {
            if (f.Id == 0)
            {
                Debug(" fill id is empty: " + f.ToString());
                return;
            }

            if (!IsTracked(f.Id))
            {
                Debug(" fill id not tracked: " + f.Id);
                return;
            }

            // add to fills
            _fills[f.Id] += f.TradeSize;
            
            Debug(f.FullSymbol + " filled size: " + _fills[f.Id] + " ; on trade detail: " + f.ToString());
        }
        private void ClientGotOrderFilled(Trade k)
        {
            _tradelist.Add(k);

            System.Windows.Application.Current.Dispatcher.Invoke(() =>
            {
                // order table
                int pos = OrderTable.Select(row => row.OrderId).ToList().IndexOf(k.Id);
                if (pos == -1)
                {
                    OnDebug("Order id " + k.Id.ToString() + " is not found in order table; possibly new order.");
                }
                else
                {
                    _ordertracker.GotFill(k);

                    if (_ordertracker[k.Id] == 0)
                    {
                        OrderStatus status = OrderStatus.Filled;
                        OrderTable[pos].Status = EnumDescConverter.GetEnumDescription(status);
                    }
                    else
                    {
                        OrderStatus status = OrderStatus.PartiallyFilled;
                        _ordertable[pos].Status = EnumDescConverter.GetEnumDescription(status);
                    }
                }

                // position table only handles one account
                // but it is guarantteed by order id
                _positiontracker.Adjust(k);
                pos = PositionTable.Select(row => row.Symbol).ToList().IndexOf(k.FullSymbol);
                if (pos == -1)
                {
                    // add new position
                    int count = PositionTable.Count;

                    PositionTable.Add(new PositionEntry(count, k.FullSymbol, _positiontracker[k.FullSymbol].AvgPrice, _positiontracker[k.FullSymbol].Size,
                        _positiontracker[k.FullSymbol].ClosedPL, _positiontracker[k.FullSymbol].OpenPL));
                }
                else
                {
                    // adjust position
                    PositionTable[pos].AvgPrice = _positiontracker[k.FullSymbol].AvgPrice;
                    PositionTable[pos].Size = _positiontracker[k.FullSymbol].Size;
                    PositionTable[pos].ClosePL = _positiontracker[k.FullSymbol].ClosedPL;
                    PositionTable[pos].OpenPL = _positiontracker[k.FullSymbol].OpenPL;
                }

                FillTable.Add(new FillEntry(k.Id, k.TradeTime, k.FullSymbol, k.TradeSize, k.TradePrice));
            });
        }
예제 #16
0
 public static string ToChartLabel(Trade fill)
 {
     return (fill.TradeSize + fill.FullSymbol);
 }
예제 #17
0
        /// <summary>
        /// this must be called once per position tracker, for each position update.
        /// if you are using your own position tracker with this trailing stop(eg from offset tracker, or somewhere else)
        /// you MUST call TrailTrackers Adjust and NOT call your position tracker's adjust
        /// </summary>
        /// <param name="fill"></param>
        public void Adjust(Trade fill)
        {
            // get index for symbol
            int idx = symidx(fill.FullSymbol);

            // only do following if we're tracking trail for this symbol
            if (idx != NOSYM)
            {
                // get current position size
                int psize = _pt[fill.FullSymbol].UnsignedSize;
                // get trailing information
                OffsetInfo trail = _trail[idx];
                // get actual position size after change
                int asize = psize - fill.UnsignedSize;
                // if expected and actual match, mark pending as false
                if (esize[fill.FullSymbol] == asize)
                {
                    D(fill.FullSymbol + " trailing stop completely filled with: " + fill.ToString());
                    _pendingfill[idx] = false;
                }
                else
                    v(fill.FullSymbol + " trail partial fill: " + fill.ToString() + " e: " + esize[fill.FullSymbol] + " != a: " + asize);

            }
            else
                v(fill.FullSymbol + " fill: " + fill.ToString() + " ignored while trail disabled.");

            _pt.Adjust(fill);
            // if we're flat now, make sure ref price is reset
            if (_pt[fill.FullSymbol].isFlat)
            {
                _ref[idx] = 0;
                v(fill.FullSymbol + " flat, reset trail reference price.");
            }
        }
예제 #18
0
        // Provides the executions which happened in the last 24 hours.
        // This event is fired when the reqExecutions() functions is invoked, or when an order is filled.
        public virtual void execDetails(int reqId, Contract contract, Execution execution)
        {
            Trade trade = new Trade();
            //trade.Currency = contract.Currency;
            trade.Account = Account;
            trade.Id = 0;

            trade.TradePrice = (decimal)execution.Price;
            trade.TradeSize = (execution.Side == "BOT"?1:-1)*execution.Shares;
            
            // FullSymbol includes SecurityType, Exchange and Multiplier
            // trade.Security = (SecurityType)EnumDescConverter.GetEnumValue(typeof(SecurityType), contract.SecType);
            trade.FullSymbol = ContractToSecurityFullName(contract);

            // convert date and time
            DateTime dt = DateTime.ParseExact(execution.Time, "yyyyMMdd  HH:mm:ss", CultureInfo.InvariantCulture);       // Two blanks
            trade.TradeDate = dt.Year * 10000 + dt.Month * 100 + dt.Day;
            trade.TradeTime = dt.Hour * 10000 + dt.Minute * 100 + dt.Second;

            if (contract.SecType != "BAG")
            {
                if (_iborderIdToOrderInfo.ContainsKey(execution.OrderId))
                {
                    trade.Id = _iborderIdToOrderInfo[execution.OrderId].StrategyOrderId;
                    if (_iborderIdToOrderInfo[execution.OrderId].IsAcknowledged)
                    {
                        OnGotFill(trade);
                        return;
                    }
                }
                // order not found or not acknowledged yet - defer fill notification
                _duplicateIBIdToDeferredTrade.Add(new KeyValuePair<int, Trade>(execution.OrderId, trade));
            }
        }
 private void ClientGotOrderFilled(Trade k)
 {
     foreach (StrategyItem si in _strategyitemlist)
     {
         si.S.GotFill(k);
     }
 }
예제 #20
0
 void OnGotFill(Trade t)
 {
     if (GotFillDelegate != null)
         GotFillDelegate(t);
 }
예제 #21
0
 public override void GotFill(Trade f)
 {
     if (_symbols.Contains(f.FullSymbol))
     {
         _positiontracker.Adjust(f);
         //int idx = Array.IndexOf(_symbols, f.FullSymbol);
         int idx = _symbols.IndexOf(f.FullSymbol);
         _waittobefilled[idx] = false;
         
         _transactions++;
         if (_transactions >= _totaltransactions)
         {
             Shutdown();
         }
     }
 }
예제 #22
0
        void _broker_GotFill(Trade f)
        {
            if (_strategy != null)
                _strategy.GotFill(f);

            // tell others, e.g. FillTable
            GotFill(f);
        }
예제 #23
0
        /// <summary>
        /// must send new fills here (eg call from Response.GotFill)
        /// </summary>
        /// <param name="t"></param>
        public void Adjust(Trade t)
        {
            // get original size
            int osize = _pt[t.symbol].Size;
            // update position
            _pt.Adjust(t);
            // see if it's our order
            OffsetInfo oi = GetOffset(t.symbol);
            // see what was hit
            bool hp = (t.id != 0) && (oi.ProfitId == t.id);
            bool hs = (t.id != 0) && (oi.StopId == t.id);
            // if we hit something
            if (hp || hs)
            {
                // notify
                debug(t.symbol + " hit " + (hp ? "profit" : "stop") + ": " + t.id);
                // see if we should clear offset
                if (hp && (oi.SentProfitSize == t.xsize))
                {
                    debug(t.symbol + " profit closed: " + t.id);
                    oi.ProfitId = 0;
                }
                else if (hp)
                    oi.SentProfitSize -= t.xsize;


                if (hs && (oi.SentStopSize == t.xsize))
                {
                    debug(t.symbol + " stop closed: " + t.id);
                    oi.StopId = 0;
                }
                else if (hs)
                    oi.SentStopSize -= t.xsize;

                if (HitOffset != null)
                    HitOffset(t.symbol, t.id, t.xprice);
            }
            // if we're flat, nothing to do (or if we switched sides)
            Position p = _pt[t.symbol];
            if (p.isFlat || (osize * p.Size < -1))
            {
                if (p.isFlat)
                    debug(t.symbol + " now flat.");
                else
                    debug(t.symbol + " reversed: " + osize + " -> " + p.Size);
                CancelAll(t.symbol);
                // reset offset state but not configuration
                SetOffset(t.symbol, new OffsetInfo(this[t.symbol]));
            }
            else // save offset
                SetOffset(t.symbol, oi);
            // do we have events?
            if (!HasEvents()) return;
            // do update
            doupdate(t.symbol);

        }
예제 #24
0
 void GotFill(Trade f)
 {
     if (GotFillEvent != null)
         GotFillEvent(f);
 }
예제 #25
0
 void _client_GotFillDelegate(Trade obj)
 {
     _eventAggregator.GetEvent<OrderFillEvent>().Publish(obj);
 }
예제 #26
0
 // these are for calculating closed pl
 // they do not adjust positions themselves
 /// <summary>
 /// Gets the closed PL on a per-share basis, ignoring how many shares are held.
 /// </summary>
 /// <param name="existing">The existing position.</param>
 /// <param name="closing">The portion of the position that's being closed/changed.</param>
 /// <returns></returns>
 public static decimal ClosePT(Position existing, Trade adjust)
 {
     if (!existing.isValid || !adjust.IsValid)
         throw new Exception("Invalid position provided. (existing:" + existing.ToString() + " adjustment:" + adjust.ToString());
     if (existing.isFlat) return 0; // nothing to close
     if (existing.isLong == adjust.Side) return 0; // if we're adding, nothing to close
     return existing.isLong ? adjust.TradePrice - existing.AvgPrice : existing.AvgPrice - adjust.TradePrice;
 }