public void ProcessLastBar(RangeBarModel bar)
 {
     // reduce inventory
     if (_currentInventory > 0)
     {
         // sell trade
         var trade = new TradeModel()
         {
             Timestamp        = bar.Timestamp,
             Price            = bar.Bid ?? bar.CurrentPrice,
             Amount           = Math.Abs(_currentInventory * _orderSize) * (-1),
             BarIndex         = _bars.Count,
             CurrentInventory = 0,
             PositionState    = PositionState.Close
         };
         _trades.Add(trade);
     }
     if (_currentInventory < 0)
     {
         // buy trade
         var trade = new TradeModel()
         {
             Timestamp        = bar.Timestamp,
             Price            = bar.Ask ?? bar.CurrentPrice,
             Amount           = Math.Abs(_currentInventory * _orderSize),
             BarIndex         = _bars.Count,
             CurrentInventory = 0,
             PositionState    = PositionState.Close
         };
         _trades.Add(trade);
     }
 }
        public void ProcessBars(RangeBarModel[] bars)
        {
            foreach (var bar in bars)
            {
                bar.Index = _bars.Count;
                _bars.Add(bar);

                var invAbs   = _currentInventory * _orderSize;
                var decision = _strategy.Decide(bar, invAbs);
                if (decision == Action.Nothing)
                {
                    continue;
                }

                var orderSize     = _orderSize;
                var positionState = PositionState.Open;

                if (decision == Action.Buy)
                {
                    if (_currentInventory < 0)
                    {
                        orderSize         = Math.Abs(_currentInventory) * orderSize;
                        _currentInventory = 0;
                        positionState     = PositionState.Close;
                    }
                    else
                    {
                        if (_maxLimitInventory.HasValue && Math.Abs(_currentInventory) >= _maxLimitInventory.Value)
                        {
                            // inventory reached, do nothing
                            continue;
                        }
                        if (_currentInventory > 0)
                        {
                            positionState = PositionState.Increase;
                        }
                        _currentInventory++;
                    }

                    var trade = new TradeModel()
                    {
                        Timestamp        = bar.Timestamp,
                        Price            = bar.Ask ?? bar.CurrentPrice,
                        Amount           = orderSize,
                        BarIndex         = _bars.Count,
                        CurrentInventory = _currentInventory,
                        PositionState    = positionState
                    };
                    _trades.Add(trade);
                    LogTrade(trade);
                }

                if (decision == Action.Sell)
                {
                    if (_currentInventory > 0)
                    {
                        orderSize         = _currentInventory * orderSize;
                        _currentInventory = 0;
                        positionState     = PositionState.Close;
                    }
                    else
                    {
                        if (_maxLimitInventory.HasValue && Math.Abs(_currentInventory) >= _maxLimitInventory.Value)
                        {
                            // inventory reached, do nothing
                            continue;
                        }
                        if (_currentInventory < 0)
                        {
                            positionState = PositionState.Increase;
                        }
                        _currentInventory--;
                    }


                    var trade = new TradeModel()
                    {
                        Timestamp        = bar.Timestamp,
                        Price            = bar.Bid ?? bar.CurrentPrice,
                        Amount           = orderSize * (-1),
                        BarIndex         = _bars.Count,
                        CurrentInventory = _currentInventory,
                        PositionState    = positionState
                    };
                    _trades.Add(trade);
                    LogTrade(trade);
                }

                _maxInventory = Math.Max(_maxInventory, Math.Abs(_currentInventory));
            }
        }
        private void LogTrade(TradeModel trade)
        {
            var side = trade.Amount < 0 ? "SELL" : "BUY";

            //Console.WriteLine();
        }
        private bool ExecuteTakerStrategy(ITakerStrategy strategy, RangeBarModel bar, double orderSize)
        {
            if (strategy == null)
            {
                return(false);
            }

            var decision = strategy.Decide(bar, _currentInventoryAbs);

            if (decision == Action.Nothing)
            {
                return(true);
            }

            var positionState = PositionState.Open;

            if (decision == Action.Buy)
            {
                if (_currentInventory < 0)
                {
                    orderSize         = Math.Abs(_currentInventory) * orderSize;
                    _currentInventory = 0;
                    positionState     = PositionState.Close;
                }
                else
                {
                    if (_maxLimitInventory.HasValue && Math.Abs(_currentInventory) >= _maxLimitInventory.Value)
                    {
                        // inventory reached, do nothing
                        return(true);
                    }

                    if (_currentInventory > 0)
                    {
                        positionState = PositionState.Increase;
                    }
                    _currentInventory++;
                }

                _currentInventoryAbs += orderSize;
                var trade = new TradeModel()
                {
                    Timestamp        = bar.TimestampUnix,
                    Price            = bar.Ask ?? bar.CurrentPrice,
                    Amount           = orderSize,
                    BarIndex         = _bars.Count,
                    CurrentInventory = _currentInventory,
                    PositionState    = positionState
                };
                _trades.Add(trade);
                LogTrade(trade);
            }

            if (decision == Action.Sell)
            {
                if (_currentInventory > 0)
                {
                    orderSize         = _currentInventory * orderSize;
                    _currentInventory = 0;
                    positionState     = PositionState.Close;
                }
                else
                {
                    if (_maxLimitInventory.HasValue && Math.Abs(_currentInventory) >= _maxLimitInventory.Value)
                    {
                        // inventory reached, do nothing
                        return(true);
                    }

                    if (_currentInventory < 0)
                    {
                        positionState = PositionState.Increase;
                    }
                    _currentInventory--;
                }

                _currentInventoryAbs -= orderSize;
                var trade = new TradeModel()
                {
                    Timestamp        = bar.TimestampUnix,
                    Price            = bar.Bid ?? bar.CurrentPrice,
                    Amount           = orderSize * (-1),
                    BarIndex         = _bars.Count,
                    CurrentInventory = _currentInventory,
                    PositionState    = positionState
                };
                _trades.Add(trade);
                LogTrade(trade);
            }

            return(false);
        }
        private void EvaluatePreviousOrders(RangeBarModel bar)
        {
            if (_placedOrders.Count <= 0)
            {
                return;
            }

            var highPrice = bar.HighBuy ?? bar.High;
            var lowPrice  = bar.LowSell ?? bar.Low;

            foreach (var placedOrder in _placedOrders.ToArray())
            {
                var orderPrice    = placedOrder.Price;
                var orderAmount   = placedOrder.Amount;
                var positionState = PositionState.Open;

                if (placedOrder.Side == OrderSide.Bid)
                {
                    if (_currentInventoryAbs < -1e-6)
                    {
                        positionState = PositionState.Close;
                    }
                    else
                    {
                        if (_maxLimitInventory.HasValue && Math.Abs(_currentInventory) >= _maxLimitInventory.Value)
                        {
                            // inventory reached, do nothing
                            _placedOrders.Remove(placedOrder);
                            continue;
                        }

                        if (_currentInventoryAbs > 1e-6)
                        {
                            positionState = PositionState.Increase;
                        }
                    }

                    if (lowPrice == null || lowPrice > orderPrice)
                    {
                        // no BUY trade, price was too high
                        continue;
                    }

                    _currentInventory++;
                    _currentInventoryAbs += orderAmount;
                    var trade = new TradeModel
                    {
                        Timestamp        = bar.TimestampUnix,
                        Price            = orderPrice,
                        Amount           = orderAmount,
                        BarIndex         = _bars.Count,
                        CurrentInventory = _currentInventory,
                        PositionState    = positionState
                    };
                    _trades.Add(trade);
                    LogTrade(trade);
                    _placedOrders.Remove(placedOrder);
                }
                else
                {
                    if (_currentInventoryAbs > 1e-6)
                    {
                        positionState = PositionState.Close;
                    }
                    else
                    {
                        if (_maxLimitInventory.HasValue && Math.Abs(_currentInventory) >= _maxLimitInventory.Value)
                        {
                            // inventory reached, do nothing
                            _placedOrders.Remove(placedOrder);
                            continue;
                        }

                        if (_currentInventoryAbs < -1e-6)
                        {
                            positionState = PositionState.Increase;
                        }
                    }

                    if (highPrice == null || highPrice < orderPrice)
                    {
                        // no SELL trade, price was too low
                        continue;
                    }

                    _currentInventory--;
                    _currentInventoryAbs -= orderAmount;
                    var trade = new TradeModel()
                    {
                        Timestamp        = bar.TimestampUnix,
                        Price            = orderPrice,
                        Amount           = orderAmount * (-1),
                        BarIndex         = _bars.Count,
                        CurrentInventory = _currentInventory,
                        PositionState    = positionState
                    };
                    _trades.Add(trade);
                    LogTrade(trade);
                    _placedOrders.Remove(placedOrder);
                }
            }
        }