public static void Main(string[] args) { bool isSimulation = true; // This is very important. Will be bubbled down to signal that this is just a simulation. try { Task.Run(async() => { // We define the list of observers here. var priceProcessors = new List <IMarketPriceProcessor>(); priceProcessors.Add(MarketPriceRecorder.Instance); priceProcessors.Add(ArbPriceManager.Instance); // priceProcessors.Add(TriangulationManager.Instance); var integrations = await DataProcessingEngine.InitializeEngine(); // Initialize the data processing engine. This returns the integrations and start the integrations engines to spit out prices. OpportunityScoreEngine.InitializeEngine(); // From the integrations and price processors we get a stream of opportunities. // Then get a stream of trade opportunities. IObservable <TradeOpportunity> tradeableStream = GetOpportunityObservable(integrations, priceProcessors.ToArray()) .GetTradeOpportunityStream(); // IScheduler s = System.Reactive.Concurrency.ThreadPoolScheduler.Instance; // Subscribe just to output to console. tradeableStream.SubscribeOn(s).Subscribe((opp) => { var state = TradeOpportunityState.States.Where(x => x.Id == opp.TradeOpportunityStateId).Single().Code; var type = TradeOpportunityType.Types.Where(x => x.Id == opp.TradeOpportunityTypeId).Single().Code; Console.WriteLine($"Opp: {opp.LatestOpportunity.UniqueIdentifier} | {state} | {opp.LatestOpportunity.GetMarginValuePercent():0.00}%"); }); // Subscribe to trade. We take only arbs over 10cents of a dollar! tradeableStream .Where(x => x.LatestOpportunity.RequirementsMet && x.LatestOpportunity.GetMaximumAmountThatCanBeTransacted() > 0m && x.LatestOpportunity.EstimateMaxUSDValue() > 0.1m) //.Select(tr => Observable.FromAsync<bool>(OpportunityScoreEngine.ExecuteTradeOpportunity())) .SubscribeOn(s) .Subscribe((opp) => { try { Console.WriteLine($"Executing Opp: {opp.LatestOpportunity.UniqueIdentifier} at profit USD {opp.LatestOpportunity.EstimateMaxUSDValue():0.00}"); var maxTx = opp.LatestOpportunity.GetMaximumAmountThatCanBeTransacted(); Task.Run(() => OpportunityScoreEngine.ExecuteTradeOpportunity(opp, maxTx, isSimulation)); } catch (Exception ex) { Console.WriteLine(""); } }, (err) => { Console.WriteLine($"err: {err.ToString()}"); } ); }).GetAwaiter().GetResult(); Console.WriteLine("Press any key to exit"); Console.ReadLine(); } catch (Exception ex) { Console.WriteLine(ex); Console.ReadLine(); } }
internal async Task UpdateOpportunity(decimal newMarginValue) { this.CurrentValue = newMarginValue; // the opportunity is only considered started on first non-zero value! if (newMarginValue == 0m) { return; } using (var ctx = new RBBotContext()) { if (this.OpportunityModel == null) { this.OpportunityModel = new TradeOpportunity() { CurrencyId = this.OpportunityBaseCurrency.Id, StartTime = DateTime.UtcNow, IsExecuted = false, TradeOpportunityTypeId = ctx.TradeOpportunityTypes.Single(x => x.Code == this.TypeCode).Id }; lock (this.OpportunityModel) { // Add it to the context. ctx.TradeOpportunities.Add(this.OpportunityModel); ctx.SaveChanges(); // Don't execute this async so we avoid having the children created before the parent! } } var newTradeValue = new TradeOpportunityValue() { PotentialMargin = newMarginValue, Timestamp = DateTime.UtcNow, TradeOpportunityId = this.OpportunityModel.Id }; ctx.TradeOpportunityValues.Add(newTradeValue); //this.OpportunityModel.TradeOpportunityValues.Add(newTradeValue); //ctx.Entry(this.OpportunityModel).State = System.Data.Entity.EntityState.Modified; //ctx.TradeOpportunityValues.Add(newTradeValue); try { await ctx.SaveChangesAsync(); } catch (Exception ex) { Console.WriteLine("Error saving opportunity to database: ", ex.ToString()); } // async save to db and return //await ctx.SaveChangesAsync(); // await OpportunityScoreEngine.UpdateOpportunityValue(this); } }