public void LoadNonVolatileVars() { lock (DbLock) { //reload my internal state BsonDocument states = Db.GetCollection("State").FindById("TradingAlgoState"); if (states != null) { State = Db.Mapper.Deserialize <NonVolatileVars>(states["State"]); //reload derived class state this.RestoreState(Db.Mapper.Deserialize <object>(states["DerivedClassState"])); //reload modules state Sentry.RestoreState(Db.Mapper.Deserialize <object>(states["Sentry"])); Allocator.RestoreState(Db.Mapper.Deserialize <object>(states["Allocator"])); Executor.RestoreState(Db.Mapper.Deserialize <object>(states["Executor"])); RiskManager.RestoreState(Db.Mapper.Deserialize <object>(states["RiskManager"])); } //rebuild symbols data foreach (var symData in Db.GetCollection <SymbolData>("SymbolsData").FindAll()) { _SymbolsData[symData.Id] = symData; } if (Db.UserVersion < 4) { foreach (var op in DbClosedOperations.FindAll().ToArray()) { op.Recalculate(); DbClosedOperations.Upsert(op); } foreach (var op in DbActiveOperations.FindAll().ToArray()) { op.Recalculate(); DbActiveOperations.Upsert(op); } Db.UserVersion = 4; Db.Checkpoint(); Db.Rebuild(); } //rebuild operations //closed operations are not loaded in current session foreach (var op in DbActiveOperations.FindAll().ToArray()) { this.AddActiveOperation(op); } } }
public void SaveNonVolatileVars() { lock (DbLock) { //save my internal state BsonDocument state = new BsonDocument(); state["_id"] = "TradingAlgoState"; state["State"] = Db.Mapper.Serialize(State); //Save derived state state["DerivedClassState"] = Db.Mapper.Serialize(GetState()); //save module states state["Sentry"] = Db.Mapper.Serialize(Sentry.GetState()); state["Allocator"] = Db.Mapper.Serialize(Allocator.GetState()); state["Executor"] = Db.Mapper.Serialize(Executor.GetState()); state["RiskManager"] = Db.Mapper.Serialize(RiskManager.GetState()); Db.GetCollection("State").Upsert(state); foreach (var symData in SymbolsData.Values) { Db.GetCollection <SymbolData>("SymbolsData").Upsert(symData); } Db.BeginTrans(); foreach (var op in ActiveOperations.Where(op => op.IsChanged)) { DbActiveOperations.Upsert(op); } foreach (var op in ClosedOperations.Where(op => op.IsChanged)) { DbClosedOperations.Upsert(op); } Db.Commit(); Db.Checkpoint(); } }
public override async Task OnStartAsync() { await this.Initialize(); await SymbolsFilter.Initialize(this); if (Sentry != null) { await Sentry.Initialize(this); } if (Allocator != null) { await Allocator.Initialize(this); } if (Executor != null) { await Executor.Initialize(this); } if (RiskManager != null) { await RiskManager.Initialize(this); } }
public async Task Update(TimeSlice slice) { LastUpdate = Market.Time; //update selected symbols var changes = await SymbolsFilter.UpdateAsync(slice); if (changes != SelectedSymbolsChanges.None) { var selectedForOperationsActive = this.ActiveOperations.Select(ao => ao.Symbol).GroupBy(ao => ao.Key).Select(g => g.First()).ToList(); //release feeds of unused symbols foreach (var sym in changes.RemovedSymbols) { SymbolData symbolData = GetSymbolData(sym); symbolData.IsSelectedForTrading = false; //if it doesn't have acrive operations if (!selectedForOperationsActive.Any(aos => aos.Key == sym.Key)) { if (symbolData.Feed != null) { symbolData.Feed.OnData -= Feed_OnData; this.ReleaseFeed(symbolData.Feed); symbolData.Feed = null; } } } //add feeds for added symbols and those that have open operations foreach (var sym in changes.AddedSymbols) { SymbolData symbolData = GetSymbolData(sym); symbolData.IsSelectedForTrading = true; } foreach (var sym in changes.AddedSymbols.Concat(selectedForOperationsActive)) { SymbolData symbolData = GetSymbolData(sym); if (symbolData.Feed == null) { symbolData.Feed = await this.GetSymbolFeed(sym.Key); symbolData.Feed.OnData -= Feed_OnData; symbolData.Feed.OnData += Feed_OnData; } } if (Sentry != null) { await Sentry.OnSymbolsChanged(changes); } if (Allocator != null) { Allocator.OnSymbolsChanged(changes); } if (Executor != null) { Executor.OnSymbolsChanged(changes); } if (RiskManager != null) { RiskManager.OnSymbolsChanged(changes); } } // register trades with their linked operations Operation[] oldOperations = null; List <Operation> operationsResumed = new List <Operation>(); foreach (ITrade trade in slice.Trades) { //first search in active operations var symData = _SymbolsData[trade.Symbol]; var activeOp = symData.ActiveOperations.FirstOrDefault(op => op.IsTradeAssociated(trade)); if (activeOp != null) { if (activeOp.AddTrade(trade)) { Logger.Info($"{Time} - New trade for operation {activeOp.ToString()}: {trade.ToString()}"); } } else { //let's search in closed operations by getting ligtweigth instances if (oldOperations == null) { //lock (DbLock) // oldOperations = oldOperations ?? DbClosedOperations.Find(o => o.CreationTime >= Market.Time.AddDays(-5)).ToArray(); lock (DbLock) oldOperations = QueryClosedOperations(doc => doc["CreationTime"].AsDateTime >= Market.Time.AddDays(-4)); } var oldOp = oldOperations.FirstOrDefault(op => op.IsTradeAssociated(trade)); //if we found an operation let's get a real instance if (oldOp != null) { oldOp = DbClosedOperations.FindById(oldOp.Id); if (oldOp == null) { Logger.Error($"Operation found then not found! {oldOp}."); } } if (oldOp != null) { operationsResumed.Add(oldOp); if (oldOp.AddTrade(trade)) { Logger.Info($"{Time} - New trade for 'old' operation {activeOp}: {trade.ToString()}"); } //check if it got resumed by this new trade if (!oldOp.IsClosed) { this.ResumeOperation(oldOp); Logger.Info($"Resuming 'old' operation {activeOp}."); } else { oldOp.Dispose(); //otherwise we must dispose it } } else { Logger.Debug($"{Time} - New trade {trade.ToString()} without any associated operation"); } } } //dispose the operations that we didn't use if (oldOperations != null) { foreach (var oper in oldOperations.Where(oo => !operationsResumed.Contains(oo))) { oper.Dispose(); } } // call OnUpdate await OnUpdate(slice); // get signals if (Sentry != null) { Sentry.UpdateAsync(slice); } //create operations if (Allocator != null) { Allocator.Update(slice); } //close operations that have been in close queue for enough time lock (DbLock) { this.Db?.BeginTrans(); List <Operation> operationsToClose = _ActiveOperations.Where(op => this.Time >= op.CloseDeadTime).ToList(); foreach (var op in operationsToClose) { if (op.AmountInvested > 0) { Logger.Info("{0} - Closing operation {1}.", Time, op.ToString("c")); } else { Logger.Debug("{0} - Closing operation {1}.", Time, op.ToString("c")); } op.Close(); _ActiveOperations.Remove(op); if (this.Config.SaveData || op.AmountInvested > 0) { this._ClosedOperations.Add(op); } this.SymbolsData[op.Symbol.Key].CloseOperation(op); if (this.Config.SaveData) { lock (DbLock) { //update database DbActiveOperations.Delete(op.Id); DbClosedOperations.Upsert(op); } } } this.Db?.Commit(); } //add new operations that have been created foreach (var op in slice.NewOperations) { AddActiveOperation(op); } //manage orders if (Executor != null) { await Executor.Update(slice); } //manage risk if (RiskManager != null) { await RiskManager.Update(slice); } while (Commands.Count > 0) { try { if (Commands.TryDequeue(out Command command)) { await command.Run(); } } catch (Exception ex) { Logger.Error($"Error while running command: {ex.Message}."); } } if (Config.SaveData) { SaveNonVolatileVars(); } }