public void ComputeNewOrders(ref TradingContext tContext)
 {
     foreach (IContextualStrategy objAction in this.Instances)
     {
         objAction.ComputeNewOrders(ref tContext);
     }
 }
        public Wallet ComputeNewOrders(Wallet currentOrders, MarketInfo objMarket, ExchangeInfo objExchange, TradingHistory history)
        {
            //the newOrders Wallet variable will contain all ask/bid/cancel orders to issue

            var newOrders = new Wallet();

            //start with reserved resource
            //Dim askReserve As Decimal = Math.Max(Me._AskReserveAmount, currentOrders.btcs * (Me._AskReserveRate / 100))
            //Dim bidReserve As Decimal = Math.Max(Me._BidReserveValue, currentOrders.usds * (Me._BidReserveRate / 100))

            decimal avBtcsForTrading = currentOrders.PrimaryBalance;
            //- askReserve
            decimal avUsdsForTrading = currentOrders.SecondaryBalance;

            //- bidReserve

            //Then We simplify the current orders by merging orders of the same price, issueing corresponding cancel/new orders
            newOrders.ConsolidateOrders(ref currentOrders, true);

            //Feed the new orders wallet with available resources, Reserve resources for current open orders
            newOrders.PrimaryBalance   = Math.Max(avBtcsForTrading - currentOrders.GetTotalAsksPrimary(), 0);
            newOrders.SecondaryBalance = Math.Max(avUsdsForTrading - currentOrders.GetTotalBidsSecondary(), 0);

            var tContext = new TradingContext(currentOrders, newOrders, objMarket, objExchange, history.GetLastTrend(), this);

            this.ComputeNewOrders(ref tContext);


            tContext.NewOrders.FitOrders(objExchange);
            //we update the trading history with last data
            history.Update(currentOrders, objMarket, tContext.NewOrders);
            return(tContext.NewOrders);
        }
 public void ComputeNewOrders(ref TradingContext tContext)
 {
     if (this.Condition.Evaluate(tContext, tContext))
     {
         this.Strategy.ComputeNewOrders(ref tContext);
         if (!string.IsNullOrEmpty(this.NewStatus))
         {
             tContext.CurrentOrders.Status = this.NewStatus;
             tContext.NewOrders.Status     = this.NewStatus;
         }
     }
 }
        public override void ComputeNewOrders(ref TradingContext tContext)
        {
            var newOrder = ReflectionHelper.CloneObject <Order>(this.StaticOrder);

            if (this.DynamicAmount)
            {
                newOrder.Amount = this.DynamicAmountExpression.Evaluate(tContext, tContext);
            }
            if (this.DynamicPrice)
            {
                newOrder.Price = this.DynamicPriceExpression.Evaluate(tContext, tContext);
            }
            if (this.DynamicType)
            {
                newOrder.Type = this.DynamicTypeExpression.Evaluate(tContext, tContext);
            }
            if (this.DynamicId)
            {
                newOrder.Oid = this.DynamicIdExpression.Evaluate(tContext, tContext);
            }
            tContext.NewOrders.Orders.Add(newOrder);
        }
        public Wallet ComputeNewOrders(Wallet currentOrders, MarketInfo objMarket, ExchangeInfo objExchange, TradingHistory history)
        {
            var newOrders  = new Wallet();
            var askReserve = Math.Max(this.AskReserveAmount, currentOrders.PrimaryBalance * AskReserveRate / 100m);
            var bidReserve = Math.Max(this.BidReserveValue, currentOrders.SecondaryBalance * BidReserveRate / 100m);

            decimal avBtcsForTrading = currentOrders.PrimaryBalance - askReserve;
            decimal avUsdsForTrading = currentOrders.SecondaryBalance - bidReserve;

            //todo: should we update the original wallet?
            newOrders.ConsolidateOrders(ref currentOrders, true);

            newOrders.PrimaryBalance   = Math.Max(avBtcsForTrading - currentOrders.GetTotalAsksPrimary(), decimal.Zero);
            newOrders.SecondaryBalance = Math.Max(decimal.Subtract(avUsdsForTrading, currentOrders.GetTotalBidsSecondary()), decimal.Zero);

            var tContext = new TradingContext(currentOrders, newOrders, objMarket, objExchange, history.GetLastTrend(), this);

            this.ComputeNewOrders(ref tContext);
            if (this.NoAsks)
            {
                tContext.NewOrders.ClearAsks();
                if (this.ClearAsks)
                {
                    tContext.NewOrders.CancelExistingOrders(tContext.CurrentOrders.OrderedAsks.ToArray());
                }
            }
            if (this.NoBids)
            {
                tContext.NewOrders.ClearBids();
                if (this.ClearBids)
                {
                    tContext.NewOrders.CancelExistingOrders(tContext.CurrentOrders.OrderedBids.ToArray());
                }
            }
            tContext.NewOrders.FitOrders(objExchange);
            history.Update(currentOrders, objMarket, tContext.NewOrders);
            return(tContext.NewOrders);
        }
Beispiel #6
0
 public BandTradingContext(TradingContext objBaseContext) : base(objBaseContext.CurrentOrders, objBaseContext.NewOrders, objBaseContext.Market, objBaseContext.Exchange, objBaseContext.LastTrend, objBaseContext.BaseStrategy)
 {
 }
 public abstract void ComputeNewOrders(ref TradingContext tContext);
Beispiel #8
0
 public override void ComputeNewOrders(ref TradingContext tContext)
 {
     this._strategies.ComputeNewOrders(ref tContext);
 }
Beispiel #9
0
        public override void ComputeNewOrders(ref TradingContext tContext)
        {
            tContext = new BandTradingContext(tContext);

            //this is because some user defined expressions are computed in loops:
            // we don't want the algorithm to get stuck in an infinite loop
            int safetyCounter = 0;

            // First we deal with asks

            if (!this.NoAsks)
            {
                if (tContext.CurrentOrders.OrderedAsks.Count == 0)
                {
                    if (this.AccountForTrend || tContext.LastTrend != TradingTrend.Ask)
                    {
                        // There is no asks order yet/anymore, define a single new ask order

                        //Compute price from current ticker and strategy
                        var newHighAskPrice = tContext.Market.Ticker.Last * (1m + DefaultBandWidthRate / 100m);

                        var newOrder = new Order()
                        {
                            OrderType = OrderType.Sell,
                            Price     = newHighAskPrice,
                            //compute amount from available balance and strategy
                            Amount = (tContext.NewOrders.PrimaryBalance * tContext.Market.Ticker.Last / newHighAskPrice)
                                     * DefaultMaxOrderValueRate / 100m
                        };
                        tContext.NewOrders.Orders.Add(newOrder);
                    }
                }
                // else: There are asks orders already, we'll base new orders according to the existing
                else if (tContext.CurrentOrders.HighestAsk.Price
                         < tContext.Market.Ticker.Last * (1m + MinBandWidthRate / 100m) ||
                         tContext.CurrentOrders.HighestAsk.Price
                         > tContext.Market.Ticker.Last * (1m + MaxBandWidthRate / 100m))
                {
                    // The band is not within defined bound: clear existing orders in order to define a new band
                    tContext.NewOrders.CancelExistingOrders(tContext.CurrentOrders.OrderedAsks.ToArray());
                }
                else if (tContext.NewOrders.PrimaryBalance * tContext.Market.Ticker.Last
                         < tContext.CurrentOrders.HighestAsk.Value * VolumeResetLimitFactor)
                {
                    //the amount of available resource is too low for the existing band: clear orders to define a new band
                    tContext.NewOrders.CancelExistingOrders(tContext.CurrentOrders.OrderedAsks.ToArray());
                }
                else
                {
                    //we start with new low orders: have we got new orders to issue ?
                    if (!AccountForTrend ||
                        tContext.LastTrend != TradingTrend.Ask ||
                        tContext.CurrentOrders.OrderedAsks.Count < 2)
                    {
                        decimal newPrice, limitPrice;
                        SimpleExpression <Decimal> pricingExpression;
                        var sign = (int)TradingBandDirection;
                        if (TradingBandDirection == TradingBandDirection.Outwards)
                        {
                            pricingExpression = NextAskOrderPriceExpression;
                            newPrice          = tContext.LowestAskLimitPrice;
                            limitPrice        = tContext.LowestAsk.Price;
                        }
                        else
                        {
                            pricingExpression = MinAskOrderPriceExpression;
                            newPrice          = pricingExpression.Evaluate(tContext, tContext);
                            limitPrice        = tContext.LowestAskLimitPrice;
                        }

                        //How close are we to the lowest limit ask price?
                        safetyCounter = 0;
                        while (newPrice > 0 && sign * newPrice < sign * limitPrice && safetyCounter < 500)
                        {
                            safetyCounter += 1;
                            // We are within the authorized inner band , place new order

                            var newOrder = new Order {
                                OrderType = OrderType.Sell, Price = newPrice
                            };

                            //set price to context to compute the new order amount
                            tContext.Price  = newPrice;
                            newOrder.Amount = AskOrderAmountExpression.Evaluate(tContext, tContext);
                            if (TradingBandDirection == TradingBandDirection.Inwards)
                            {
                                tContext.NewOrders.Orders.Add(newOrder);
                            }
                            newPrice = pricingExpression.Evaluate(tContext, tContext);
                            if (TradingBandDirection == TradingBandDirection.Outwards &&
                                sign * newPrice < sign * limitPrice)
                            {
                                tContext.NewOrders.Orders.Add(newOrder);
                            }
                        }
                    }

                    //then we check existing orders for cancelling or increasing
                    for (var i = 0; i <= tContext.CurrentOrders.OrderedAsks.Count - 1; i++)
                    {
                        var currentOrder = tContext.CurrentOrders.OrderedAsks[i];
                        if (currentOrder.Price > tContext.LowestAskLimitPrice)
                        {
                            tContext.Price = currentOrder.Price;
                            decimal idealAmount = AskOrderAmountExpression.Evaluate(tContext, tContext);
                            //Cleaning: if the order span exceeds the previous order span
                            //by more than the defined canceling rate, cancel the order
                            if ((i > 1 &&
                                 (tContext.CurrentOrders.OrderedAsks[i].Price - tContext.CurrentOrders.OrderedAsks[i - 1].Price)
                                 /
                                 (tContext.CurrentOrders.OrderedAsks[i - 1].Price - tContext.CurrentOrders.OrderedAsks[i - 2].Price)
                                 < this.CancelOrderLimitRate / 100m))
                            {
                                tContext.NewOrders.CancelExistingOrders(currentOrder);
                            }
                            else if (currentOrder.Amount < idealAmount * AdjustOrderLimitRate / 100m)
                            {
                                var newOrder = new Order {
                                    OrderType = OrderType.Sell,
                                    Price     = currentOrder.Price,
                                    Amount    = idealAmount
                                };

                                //new order amount is the difference between ideal amount and current amount
                                tContext.NewOrders.CancelExistingOrders(currentOrder);
                                tContext.NewOrders.Orders.Add(newOrder);
                            }
                        }
                    }

                    if (tContext.NewOrders.Orders.Count == 0 &&
                        tContext.NewOrders.PrimaryBalance * tContext.Market.Ticker.Last
                        > tContext.CurrentOrders.HighestAsk.Value * VolumeGrowthLimitFactor)
                    {
                        //if their are still btcs available and their amount exceeds the strategy limit, increase the higher order
                        var newOrder = new Order
                        {
                            OrderType = OrderType.Sell,
                            Price     = tContext.CurrentOrders.HighestAsk.Price,
                            Amount    = tContext.CurrentOrders.HighestAsk.Amount * (1 + this.VolumeGrowthRate / 100m)
                        };
                        tContext.NewOrders.CancelExistingOrders(tContext.CurrentOrders.HighestAsk);
                        tContext.NewOrders.Orders.Add(newOrder);
                    }
                }
            }



            // Then we deal with Bids

            //todo: that should be symetrical thus abstracted as such

            if (!this.NoBids)
            {
                if (tContext.CurrentOrders.OrderedBids.Count == 0)
                {
                    if (this.AccountForTrend || tContext.LastTrend != TradingTrend.Bid)
                    {
                        // There is no bid order yet/anymore, define a single new bid order

                        //Compute price from current ticker and strategy
                        var newLowBidPrice = tContext.Market.Ticker.Last * 100m / (DefaultBandWidthRate + 100m);

                        var newOrder = new Order()
                        {
                            OrderType = OrderType.Buy,
                            Price     = newLowBidPrice,
                            //compute amount from available balance and strategy
                            Amount = (tContext.NewOrders.SecondaryBalance / newLowBidPrice)
                                     * DefaultMaxOrderValueRate / 100m
                        };
                        tContext.NewOrders.Orders.Add(newOrder);
                    }
                }
                // else: There are bid orders already, we'll base new orders according to the existing
                else if (tContext.CurrentOrders.LowestBid.Price
                         > tContext.Market.Ticker.Last * 100m / (MinBandWidthRate + 100m) ||
                         tContext.CurrentOrders.LowestBid.Price
                         < tContext.Market.Ticker.Last * 100m / (MaxBandWidthRate + 100m))
                {
                    // The band is not within defined bound: clear existing orders in order to define a new band
                    tContext.NewOrders.CancelExistingOrders(tContext.CurrentOrders.OrderedBids.ToArray());
                }
                else if (tContext.NewOrders.SecondaryBalance
                         < tContext.CurrentOrders.LowestBid.Value * VolumeResetLimitFactor)
                {
                    //the amount of available resource is too low for the existing band: clear orders to define a new band
                    tContext.NewOrders.CancelExistingOrders(tContext.CurrentOrders.OrderedBids.ToArray());
                }
                else
                {
                    //we start with new low orders: have we got new orders to issue ?
                    if (!AccountForTrend ||
                        tContext.LastTrend != TradingTrend.Bid ||
                        tContext.CurrentOrders.OrderedBids.Count < 2)
                    {
                        decimal newPrice, limitPrice;
                        SimpleExpression <Decimal> pricingExpression;
                        var sign = (int)TradingBandDirection;
                        if (TradingBandDirection == TradingBandDirection.Outwards)
                        {
                            pricingExpression = NextBidOrderPriceExpression;
                            newPrice          = tContext.HighestBidLimitPrice;
                            limitPrice        = tContext.HighestBid.Price;
                        }
                        else
                        {
                            pricingExpression = MaxBidOrderPriceExpression;
                            newPrice          = pricingExpression.Evaluate(tContext, tContext);
                            limitPrice        = tContext.HighestBidLimitPrice;
                        }

                        //How close are we to the lowest limit ask price?
                        safetyCounter = 0;
                        while (newPrice > 0 && sign * newPrice > sign * limitPrice && safetyCounter < 500)
                        {
                            safetyCounter += 1;
                            // We are within the authorized inner band , place new order

                            var newOrder = new Order {
                                OrderType = OrderType.Buy, Price = newPrice
                            };

                            //set price to context to compute the new order amount
                            tContext.Price  = newPrice;
                            newOrder.Amount = BidOrderAmountExpression.Evaluate(tContext, tContext);
                            if (TradingBandDirection == TradingBandDirection.Inwards)
                            {
                                tContext.NewOrders.Orders.Add(newOrder);
                            }
                            newPrice = pricingExpression.Evaluate(tContext, tContext);
                            if (TradingBandDirection == TradingBandDirection.Outwards &&
                                sign * newPrice > sign * limitPrice)
                            {
                                tContext.NewOrders.Orders.Add(newOrder);
                            }
                        }
                    }

                    //then we check existing orders for cancelling or increasing
                    for (var i = 0; i <= tContext.CurrentOrders.OrderedBids.Count - 1; i++)
                    {
                        var currentOrder = tContext.CurrentOrders.OrderedBids[i];
                        if (currentOrder.Price < tContext.HighestBidLimitPrice)
                        {
                            tContext.Price = currentOrder.Price;
                            decimal idealAmount = BidOrderAmountExpression.Evaluate(tContext, tContext);
                            //Cleaning: if the order span exceeds the previous order span
                            //by more than the defined canceling rate, cancel the order
                            if ((i < tContext.CurrentOrders.OrderedBids.Count - 2 &&
                                 (tContext.CurrentOrders.OrderedBids[i + 1].Price - tContext.CurrentOrders.OrderedBids[i].Price)
                                 /
                                 (tContext.CurrentOrders.OrderedBids[i + 2].Price - tContext.CurrentOrders.OrderedBids[i + 1].Price)
                                 < this.CancelOrderLimitRate / 100m))
                            {
                                tContext.NewOrders.CancelExistingOrders(currentOrder);
                            }
                            else if (currentOrder.Amount < idealAmount * AdjustOrderLimitRate / 100m)
                            {
                                var newOrder = new Order
                                {
                                    OrderType = OrderType.Buy,
                                    Price     = currentOrder.Price,
                                    Amount    = idealAmount
                                };

                                //new order amount is the difference between ideal amount and current amount
                                tContext.NewOrders.CancelExistingOrders(currentOrder);
                                tContext.NewOrders.Orders.Add(newOrder);
                            }
                        }
                    }

                    if (tContext.NewOrders.Orders.Count == 0 &&
                        tContext.NewOrders.SecondaryBalance
                        > tContext.CurrentOrders.LowestBid.Value * VolumeGrowthLimitFactor)
                    {
                        //if their are still resources available and their amount exceeds the strategy limit, increase the highest order
                        var newOrder = new Order
                        {
                            OrderType = OrderType.Buy,
                            Price     = tContext.CurrentOrders.LowestBid.Price,
                            Amount    = tContext.CurrentOrders.LowestBid.Amount * (1 + this.VolumeGrowthRate / 100m)
                        };
                        tContext.NewOrders.CancelExistingOrders(tContext.CurrentOrders.LowestBid);
                        tContext.NewOrders.Orders.Add(newOrder);
                    }
                }
            }
        }