public void One_Negative_PnL_And_Threshold_Is_Exceeded() { // arrange var interval = TimeSpan.FromSeconds(1); var threshold = 100; var markup = 0.002m; var negativePnL = -100.00000001m; var pnLStopLossEngine = new PnLStopLossEngine { Id = Guid.NewGuid().ToString(), Mode = PnLStopLossEngineMode.Idle, Interval = interval, Threshold = threshold, Markup = markup }; // act pnLStopLossEngine.AddNegativePnL(negativePnL); pnLStopLossEngine.Refresh(); // assert Assert.IsFalse(string.IsNullOrWhiteSpace(pnLStopLossEngine.Id)); Assert.AreEqual(pnLStopLossEngine.Interval, interval); Assert.AreEqual(pnLStopLossEngine.Threshold, threshold); Assert.AreEqual(pnLStopLossEngine.Markup, markup); Assert.AreEqual(pnLStopLossEngine.Mode, PnLStopLossEngineMode.Active); Assert.AreEqual(pnLStopLossEngine.TotalNegativePnL, negativePnL); Assert.IsNotNull(pnLStopLossEngine.StartTime); Assert.IsNotNull(pnLStopLossEngine.LastTime); }
public async Task AddAsync(PnLStopLossEngine pnLStopLossEngine) { if (!string.IsNullOrWhiteSpace(pnLStopLossEngine.Id)) { throw new InvalidOperationException("PnL stop loss engine already has an identifier."); } if (await _instrumentService.TryGetByAssetPairIdAsync(pnLStopLossEngine.AssetPairId) == null) { throw new InvalidOperationException($"Asset pair id is not found: '{pnLStopLossEngine.AssetPairId}'."); } if (string.IsNullOrWhiteSpace(pnLStopLossEngine.AssetPairId)) { throw new InvalidOperationException("PnL stop loss engine must contain asset pair id."); } pnLStopLossEngine.Id = Guid.NewGuid().ToString(); pnLStopLossEngine.Mode = PnLStopLossEngineMode.Idle; _log.InfoWithDetails("Creating pnl stop loss engine.", pnLStopLossEngine); await _pnLStopLossEngineRepository.InsertAsync(pnLStopLossEngine); _cache.Set(pnLStopLossEngine); _log.InfoWithDetails("PnL stop loss engine created.", pnLStopLossEngine); }
public void Initialized_And_Refreshed_Without_Negative_PnL() { // arrange var interval = TimeSpan.FromSeconds(1); var threshold = 100; var markup = 0.002m; var pnLStopLossEngine = new PnLStopLossEngine { Id = Guid.NewGuid().ToString(), Mode = PnLStopLossEngineMode.Idle, Interval = interval, Threshold = threshold, Markup = markup }; // act pnLStopLossEngine.Refresh(); // assert Assert.IsFalse(string.IsNullOrWhiteSpace(pnLStopLossEngine.Id)); Assert.AreEqual(pnLStopLossEngine.Interval, interval); Assert.AreEqual(pnLStopLossEngine.Threshold, threshold); Assert.AreEqual(pnLStopLossEngine.Markup, markup); Assert.AreEqual(pnLStopLossEngine.Mode, PnLStopLossEngineMode.Idle); Assert.AreEqual(pnLStopLossEngine.TotalNegativePnL, 0); Assert.IsNull(pnLStopLossEngine.StartTime); Assert.IsNull(pnLStopLossEngine.LastTime); }
public async Task PnL_Stop_Loss_First_Position_With_Exceeded_Threshold_Test() { // arrange var pnLStopLossEngineService = GetInstance(); var engine = new PnLStopLossEngine { AssetPairId = AssetPairId, Interval = TimeSpan.FromSeconds(3), Markup = 0.03m, Threshold = 100 }; await pnLStopLossEngineService.AddAsync(engine); // act var position = new Position { AssetPairId = AssetPairId, PnL = -100 }; await pnLStopLossEngineService.HandleClosedPositionAsync(position); // assert engine = (await pnLStopLossEngineService.GetAllAsync()).Single(); Assert.AreEqual(PnLStopLossEngineMode.Active, engine.Mode); Assert.AreEqual(-100m, engine.TotalNegativePnL); var markup = await pnLStopLossEngineService.GetTotalMarkupByAssetPairIdAsync(AssetPairId); Assert.AreEqual(0.03m, markup); }
public async Task InsertAsync(PnLStopLossEngine pnLStopLossEngine) { var newEntity = new PnLStopLossEngineEntity(GetPartitionKey(), GetRowKey(pnLStopLossEngine.Id)); Mapper.Map(pnLStopLossEngine, newEntity); await _storage.InsertThrowConflictAsync(newEntity); }
public async Task UpdateAsync(PnLStopLossEngine pnLStopLossEngine) { await _storage.MergeAsync(GetPartitionKey(), GetRowKey(pnLStopLossEngine.Id), entity => { Mapper.Map(pnLStopLossEngine, entity); return(entity); }); }
private async Task Refresh(PnLStopLossEngine pnLStopLossEngine) { var isUpdated = pnLStopLossEngine.Refresh(); if (isUpdated) { await UpdateAsync(pnLStopLossEngine); } }
private async Task CreateEngine(string assetPairId, Domain.PnLStopLossSettings pnLStopLossSettings) { PnLStopLossEngine newEngine = new PnLStopLossEngine(pnLStopLossSettings); newEngine.AssetPairId = assetPairId; newEngine.PnLStopLossSettingsId = pnLStopLossSettings.Id; await _pnLStopLossEngineService.AddAsync(newEngine); }
private async Task <PnLStopLossEngine> GetEngineByIdAsync(string id) { IReadOnlyCollection <PnLStopLossEngine> pnLStopLossEngines = await GetAllAsync(); PnLStopLossEngine pnLStopLossSettings = pnLStopLossEngines.FirstOrDefault(o => o.Id == id); if (pnLStopLossSettings == null) { throw new EntityNotFoundException(); } return(pnLStopLossSettings); }
public async Task UpdateAsync(PnLStopLossEngine pnLStopLossEngine) { if (string.IsNullOrWhiteSpace(pnLStopLossEngine.Id)) { throw new InvalidOperationException("PnL stop loss engine must have an identifier."); } PnLStopLossEngine currentPnLStopLossEngine = await GetEngineByIdAsync(pnLStopLossEngine.Id); currentPnLStopLossEngine.Update(pnLStopLossEngine); await _pnLStopLossEngineRepository.UpdateAsync(currentPnLStopLossEngine); _cache.Set(currentPnLStopLossEngine); _log.InfoWithDetails("PnL stop loss engine updated.", currentPnLStopLossEngine); }
public async Task PnL_Stop_Loss_Complex_Test() { // arrange var pnLStopLossEngineService = GetInstance(); var engine = new PnLStopLossEngine { AssetPairId = AssetPairId, Interval = TimeSpan.FromSeconds(2), Markup = 0.03m, Threshold = 100 }; await pnLStopLossEngineService.AddAsync(engine); // act var position = new Position { AssetPairId = AssetPairId, PnL = -50 }; await pnLStopLossEngineService.HandleClosedPositionAsync(position); // assert that negative PnL in NOT enough engine = (await pnLStopLossEngineService.GetAllAsync()).Single(); Assert.AreEqual(PnLStopLossEngineMode.Idle, engine.Mode); Assert.AreEqual(-50m, engine.TotalNegativePnL); var markup = await pnLStopLossEngineService.GetTotalMarkupByAssetPairIdAsync(AssetPairId); Assert.AreEqual(0m, markup); Thread.Sleep(1 * 1000); // act position = new Position { AssetPairId = AssetPairId, PnL = -51 }; await pnLStopLossEngineService.HandleClosedPositionAsync(position); Thread.Sleep(1 * 1000); await pnLStopLossEngineService.ExecuteAsync(); // assert that negative PnL in enough engine = (await pnLStopLossEngineService.GetAllAsync()).Single(); Assert.AreEqual(PnLStopLossEngineMode.Active, engine.Mode); Assert.AreEqual(-101m, engine.TotalNegativePnL); markup = await pnLStopLossEngineService.GetTotalMarkupByAssetPairIdAsync(AssetPairId); Assert.AreEqual(0.03m, markup); // wait until interval is up Thread.Sleep(2 * 1000); await pnLStopLossEngineService.ExecuteAsync(); // assert again that engine is off and markup is 0 engine = (await pnLStopLossEngineService.GetAllAsync()).Single(); Assert.AreEqual(PnLStopLossEngineMode.Idle, engine.Mode); Assert.AreEqual(0m, engine.TotalNegativePnL); markup = await pnLStopLossEngineService.GetTotalMarkupByAssetPairIdAsync(AssetPairId); Assert.AreEqual(0m, markup); }