public void ComputeFees(CommercialAccount objAccount, TradingHistory history) { if (DateTime.Now > this.StartDate) { if (objAccount.PastDebits.Count == 0) { //todo: handle that case } else { if (objAccount.LastDebit.Time.Subtract(objAccount.FirstDebit.Time) > TrialDuration.Value) { foreach (CommercialFee objFee in Fees.Instances) { List <WalletPayment> feeList; if (!objAccount.PastDebits.TryGetValue(objFee.Name, out feeList)) { feeList = new List <WalletPayment>(); objAccount.PastDebits[objFee.Name] = feeList; } if (feeList.Count == 0 || feeList[0].Time.Add(objFee.Period.Value) < DateTime.Now) { var newPayment = objFee.ComputePayment(history); objAccount.AddDebit(objFee, newPayment); } } } } } }
public void ExecuteOrders(MarketInfo objMarket, ref Wallet targetWallet, ref TradingHistory history) { var trades = new List <Trade>(); var fees = new List <Payment>(); var matchedOrders = this.MatchOrders(ref targetWallet, objMarket.Ticker.Last); foreach (var matchedOrder in matchedOrders) { Trade trade = new Trade() { Time = objMarket.Time, Price = matchedOrder.Price, Amount = matchedOrder.Amount }; Payment fee = new Payment() { Time = objMarket.Time, Label = matchedOrder.FriendlyId }; if (matchedOrder.OrderType == OrderType.Buy) { trade.TradeType = TradeType.Buy; fee.Currency = objMarket.PrimaryCode; fee.Amount = matchedOrder.Amount * BidCommission / 100m; fee.Label = string.Format("{0} - Bid Fee: {1} % = {2} {3}" , fee.Label , BidCommission.ToString(CultureInfo.InvariantCulture) , fee.Amount , fee.Currency); targetWallet.SecondaryBalance = targetWallet.SecondaryBalance - matchedOrder.Value; targetWallet.PrimaryBalance = targetWallet.PrimaryBalance + matchedOrder.Amount - fee.Amount; } else if (matchedOrder.OrderType == OrderType.Sell) { trade.TradeType = TradeType.Sell; fee.Currency = objMarket.SecondaryCode; fee.Amount = matchedOrder.Value * AskCommission / 100m; fee.Label = string.Format("{0} - Ask Fee: {1} % = {2} {3}" , fee.Label , AskCommission.ToString(CultureInfo.InvariantCulture) , fee.Amount , fee.Currency); targetWallet.SecondaryBalance = targetWallet.SecondaryBalance + matchedOrder.Value - fee.Amount; targetWallet.PrimaryBalance = targetWallet.PrimaryBalance - matchedOrder.Amount; } trades.Add(trade); fees.Add(fee); targetWallet.Orders.Remove(matchedOrder); } targetWallet.Time = objMarket.Time; history.Update(targetWallet, objMarket, trades, fees); }
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 WalletPayment ComputePayment(TradingHistory history) { WalletPayment ComputePayment = null; return(ComputePayment); }
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); }
/// <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); }