public TradingContext(Wallet currentOrders, Wallet newOrders, MarketInfo objMarket, ExchangeInfo objExchange, TradingTrend lastTrend, ITradingStrategy objStrategy) { this.Exchange = new ExchangeInfo(); this.Market = new MarketInfo(); this.CurrentOrders = new Wallet(); this.NewOrders = new Wallet(); this.CurrentOrders = currentOrders; this.NewOrders = newOrders; this.Market = objMarket; this.Exchange = objExchange; this.LastTrend = lastTrend; this.BaseStrategy = objStrategy; }
/// <summary> /// Static method that runs a simulation of a Market and bot runs for a given period, /// with the parameters and historical data supplied as parameters /// </summary> /// <param name="objSimulation">An instance of the simulation info class with properties defining how to perform the simulation</param> /// <param name="initialWallet">The Wallet to use at the start of the simulation</param> /// <param name="obStrategy">The existing strategy to use if the simulation object does not specify a custom strategy</param> /// <param name="objExchange">An instance of the Exchange parameters</param> /// <param name="exchangeHistory">Historical data for the Exchange object</param> /// <returns>the trading history computed from the simulation with resulting balance, issued and executed orders</returns> public static TradingHistory RunSimulation(SimulationInfo objSimulation, Wallet initialWallet , ITradingStrategy obStrategy, ExchangeInfo objExchange, IEnumerable <Trade> exchangeHistory) { var toReturn = new TradingHistory(); if (objSimulation.UseCustomStrategy) { obStrategy = objSimulation.CustomStrategy; } var objExchangeSimulator = new ExchangeSimulator() { Trades = exchangeHistory.ToList() }; var currentWallet = (Wallet)initialWallet.Clone(); //var lastBotMarket = new MarketInfo(DateTime.MinValue); var lastBotTicker = 0m; var lastBotTime = DateTime.MinValue; MarketInfo objMarket = null; int nbEmptyRuns = 0; foreach (var historicTrade in objExchangeSimulator.Trades .Where(objTrade => objTrade.Time > objSimulation.StartDate && objTrade.Time < objSimulation.EndDate)) { if ((currentWallet.OrderedAsks.Count > 0 && historicTrade.Price > currentWallet.LowestAsk.Price) || (currentWallet.OrderedBids.Count > 0 && historicTrade.Price < currentWallet.HighestBid.Price)) { nbEmptyRuns = 0; objMarket = objExchangeSimulator.GetMarket(historicTrade.Time); objExchange.ExecuteOrders(objMarket, ref currentWallet, ref toReturn); } if (historicTrade.Time.Subtract(lastBotTime) > objSimulation.BotPeriod.Value) { currentWallet.Time = historicTrade.Time; bool isBigVariation = Math.Abs((historicTrade.Price - lastBotTicker) / historicTrade.Price) > objSimulation.SkippedVariationRate / 100; if (!objSimulation.FastSimulation || nbEmptyRuns < objSimulation.SkippedMinVoidRuns || nbEmptyRuns >= objSimulation.SkippedMaxRuns || isBigVariation) { if (objMarket == null) { objMarket = objExchangeSimulator.GetMarket(historicTrade.Time); } var newOrders = obStrategy.ComputeNewOrders(currentWallet, objMarket, objExchange, toReturn); currentWallet.IntegrateOrders(newOrders.Orders.ToArray()); lastBotTicker = objMarket.Ticker.Last; if (newOrders.Orders.Count == 0 && !isBigVariation && nbEmptyRuns < objSimulation.SkippedMaxRuns) { nbEmptyRuns++; } else { nbEmptyRuns = 0; } } else { nbEmptyRuns++; } lastBotTime = historicTrade.Time; } objMarket = null; } return(toReturn); }
/// <summary> /// Updates the orders according to the available balance (overflow orders are removed), and to the exchange min order settings. /// </summary> /// <param name="exchange">the exchange defining minimum order settings</param> public void FitOrders(ExchangeInfo exchange) { this.ConsolidateOrders(); //first we fit orders according to the available resources decimal totalBids = this.GetTotalBidsSecondary(); if (totalBids > 0) { var coefBids = Math.Max(this.SecondaryBalance, 0) / totalBids; if (coefBids < 1) { decimal cumulativeBids = 0; foreach (var bid in this.OrderedBids) { //bid.amount = Decimal.Round(bid.amount * coefBids, exchange.AmountDecil, MidpointRounding.ToEven) cumulativeBids += bid.Value; if (cumulativeBids > this.SecondaryBalance) { this.Orders.Remove(bid); } } } } var totalAsks = this.GetTotalAsksPrimary(); if (totalAsks > 0) { var coefAsks = Math.Max(this.PrimaryBalance, 0) / totalAsks; if (coefAsks < 1) { decimal cumulativeAsks = 0; var decreasingAsks = this.OrderedAsks; decreasingAsks.Reverse(); foreach (var ask in decreasingAsks) { //ask.amount = Decimal.Round(ask.amount * coefAsks, exchange.AmountDecil, MidpointRounding.ToEven) cumulativeAsks += ask.Amount; if (cumulativeAsks > this.PrimaryBalance) { _orders.Remove(ask); } } } } var cleanOrders = new List <Order>(); foreach (var objOrder in _orders) { if (objOrder.IsCancel) { cleanOrders.Add(objOrder); } else { if (objOrder.Amount >= Math.Max(exchange.MinOrderAmount, exchange.MinOrderValue / objOrder.Price)) { objOrder.Price = decimal.Round(objOrder.Price, exchange.PriceDecil); objOrder.Amount = decimal.Round(objOrder.Amount, exchange.AmountDecil); cleanOrders.Add(objOrder); } } } Orders = cleanOrders; }
public TradingHistory RunSimulation(Wallet initialWallet, ITradingStrategy obStrategy, ExchangeInfo objExchange, IEnumerable <Trade> exchangeHistory) { return(SimulationInfo.RunSimulation(this, initialWallet, obStrategy, objExchange, exchangeHistory)); }