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);
        }
예제 #2
0
        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);
     });
 }
예제 #7
0
        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);
        }
예제 #9
0
        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);
        }
예제 #10
0
        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);
        }