Esempio n. 1
0
 public bool TryGet(string key, out OvernightSwapCalculation item)
 {
     lock (LockObj)
     {
         return(_cache.TryGetValue(key, out item));
     }
 }
Esempio n. 2
0
        /// <summary>
        /// Log failed orders.
        /// </summary>
        /// <param name="orders"></param>
        /// <param name="accountId"></param>
        /// <param name="instrument"></param>
        /// <param name="exception"></param>
        /// <returns></returns>
        private async Task ProcessFailedOrders(IEnumerable <Order> orders, string accountId, string instrument,
                                               Exception exception)
        {
            var failedCalculation = OvernightSwapCalculation.Create(accountId, instrument,
                                                                    orders.Select(o => o.Id).ToList(), _currentStartTimestamp, false, exception);

            await _log.WriteErrorAsync(nameof(OvernightSwapService), nameof(ProcessFailedOrders),
                                       new Exception(failedCalculation.ToJson()), DateTime.UtcNow);

            await _overnightSwapHistoryRepository.AddAsync(failedCalculation);
        }
Esempio n. 3
0
        public void Remove(OvernightSwapCalculation item)
        {
            if (item == null)
            {
                return;
            }

            lock (LockObj)
            {
                _cache.Remove(item.Key);
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Log failed orders.
        /// </summary>
        /// <param name="order"></param>
        /// <param name="clientId"></param>
        /// <param name="accountId"></param>
        /// <param name="instrument"></param>
        /// <param name="exception"></param>
        /// <returns></returns>
        private async Task ProcessFailedOrder(Order order, string clientId, string accountId,
                                              string instrument, Exception exception)
        {
            var volume            = order.Volume;
            var failedCalculation = OvernightSwapCalculation.Create(clientId, accountId, instrument,
                                                                    order.Id, _currentStartTimestamp, false, exception, volume);

            await _log.WriteErrorAsync(nameof(OvernightSwapService), nameof(ProcessFailedOrder),
                                       new Exception(failedCalculation.ToJson()), DateTime.UtcNow);

            await _overnightSwapHistoryRepository.AddAsync(failedCalculation);
        }
Esempio n. 5
0
        /// <summary>
        /// Log failed orders.
        /// </summary>
        /// <param name="orders"></param>
        /// <param name="clientId"></param>
        /// <param name="accountId"></param>
        /// <param name="instrument"></param>
        /// <param name="exception"></param>
        /// <returns></returns>
        private async Task ProcessFailedOrders(IReadOnlyList <Order> orders, string clientId, string accountId,
                                               string instrument, Exception exception)
        {
            var volume            = orders.Select(x => Math.Abs(x.Volume)).Sum();
            var failedCalculation = OvernightSwapCalculation.Create(clientId, accountId, instrument,
                                                                    orders.Select(o => o.Id).ToList(), _currentStartTimestamp, false, exception, volume);

            await _log.WriteErrorAsync(nameof(OvernightSwapService), nameof(ProcessFailedOrders),
                                       new Exception(failedCalculation.ToJson()), DateTime.UtcNow);

            await _overnightSwapHistoryRepository.AddAsync(failedCalculation);
        }
Esempio n. 6
0
        public bool AddOrReplace(OvernightSwapCalculation item)
        {
            if (item == null)
            {
                return(false);
            }

            lock (LockObj)
            {
                _cache.Remove(item.Key);
                _cache[item.Key] = item;
            }

            return(true);
        }
Esempio n. 7
0
        /// <summary>
        /// Calculate overnight swaps for account/instrument/direction order package.
        /// </summary>
        /// <param name="instrument"></param>
        /// <param name="account"></param>
        /// <param name="accountAssetPair"></param>
        /// <param name="direction"></param>
        /// <param name="orders"></param>
        /// <returns></returns>
        private async Task ProcessOrders(IReadOnlyList <Order> orders, string instrument, IMarginTradingAccount account,
                                         IAccountAssetPair accountAssetPair, OrderDirection direction)
        {
            //check if swaps had already been taken
            if (_overnightSwapCache.TryGet(OvernightSwapCalculation.GetKey(account.Id, instrument, direction),
                                           out var lastCalc) &&
                lastCalc.Time > CalcLastInvocationTime)
            {
                throw new Exception($"Overnight swaps had already been taken: {JsonConvert.SerializeObject(lastCalc)}");
            }

            //calc swaps
            var swapRate = direction == OrderDirection.Buy ? accountAssetPair.OvernightSwapLong : accountAssetPair.OvernightSwapShort;

            if (swapRate == 0)
            {
                return;
            }

            var total = orders.Sum(order => _commissionService.GetOvernightSwap(order, swapRate));

            if (total == 0)
            {
                return;
            }

            //create calculation obj & add to cache
            var calculation = OvernightSwapCalculation.Create(account.Id, instrument,
                                                              orders.Select(order => order.Id).ToList(), _currentStartTimestamp, true, null, total, swapRate, direction);

            _overnightSwapCache.AddOrReplace(calculation);

            //charge comission
            await _accountManager.UpdateBalanceAsync(
                account : account,
                amount : -total,
                historyType : AccountHistoryType.Swap,
                comment : $"{accountAssetPair.Instrument} {(direction == OrderDirection.Buy ? "long" : "short")} swaps. Positions count: {orders.Count}. Rate: {swapRate}. Time: {_currentStartTimestamp:u}.",
                auditLog : calculation.ToJson());

            //write state and log
            await _overnightSwapStateRepository.AddOrReplaceAsync(calculation);

            await _overnightSwapHistoryRepository.AddAsync(calculation);
        }
Esempio n. 8
0
        public bool TryAdd(OvernightSwapCalculation item)
        {
            if (item == null)
            {
                return(false);
            }

            lock (LockObj)
            {
                if (_cache.ContainsKey(item.Key))
                {
                    return(false);
                }

                _cache[item.Key] = item;
                return(true);
            }
        }
Esempio n. 9
0
        /// <summary>
        /// Calculate overnight swaps for account order.
        /// </summary>
        /// <param name="account"></param>
        /// <param name="accountAssetPair"></param>
        /// <param name="order"></param>
        /// <returns></returns>
        private async Task ProcessOrder(Order order, IMarginTradingAccount account,
                                        IAccountAssetPair accountAssetPair)
        {
            //check if swaps had already been taken
            var lastCalcExists = _overnightSwapCache.TryGet(OvernightSwapCalculation.GetKey(order.Id),
                                                            out var lastCalc) &&
                                 lastCalc.Time >= CalcLastInvocationTime();

            if (lastCalcExists)
            {
                await _log.WriteErrorAsync(nameof(OvernightSwapService), nameof(ProcessOrder),
                                           new Exception($"Overnight swap had already been taken, filtering: {JsonConvert.SerializeObject(lastCalc)}"), DateTime.UtcNow);
            }

            //calc swaps
            var swapRate = order.GetOrderType() == OrderDirection.Buy ? accountAssetPair.OvernightSwapLong : accountAssetPair.OvernightSwapShort;

            if (swapRate == 0)
            {
                await _log.WriteInfoAsync(nameof(OvernightSwapService), nameof(ProcessOrder),
                                          $"Overnight swap rate on order {order.Id } is 0, what will not be calculated", DateTime.UtcNow);

                return;
            }

            //special rule for Wednesday
            if (_currentStartTimestamp.DayOfWeek == DayOfWeek.Wednesday)
            {
                swapRate *= 3;
            }

            var total = _commissionService.GetOvernightSwap(order, swapRate);

            if (total == 0)
            {
                await _log.WriteInfoAsync(nameof(OvernightSwapService), nameof(ProcessOrder),
                                          $"Overnight swap rate on order {order.Id } is 0, what will not be calculated", DateTime.UtcNow);

                return;
            }

            //create calculation obj & add to cache
            var volume      = order.Volume;
            var calculation = OvernightSwapCalculation.Create(account.ClientId, account.Id, order.Instrument,
                                                              order.Id, _currentStartTimestamp, true, null, volume, total, swapRate, order.GetOrderType());

            await _accountManager.UpdateBalanceAsync(
                account : account,
                amount : -total,
                historyType : AccountHistoryType.Swap,
                comment : $"Position {order.Id}  swaps. Time: {_currentStartTimestamp:u}.",
                auditLog : calculation.ToJson(),
                eventSourceId : order.Id);

            //update calculation state if previous existed
            var newCalcState = lastCalcExists
                ? OvernightSwapCalculation.Update(calculation, lastCalc)
                : OvernightSwapCalculation.Create(calculation);

            //add to cache
            _overnightSwapCache.AddOrReplace(newCalcState);

            //write state and log
            await _overnightSwapStateRepository.AddOrReplaceAsync(newCalcState);

            await _overnightSwapHistoryRepository.AddAsync(calculation);
        }
Esempio n. 10
0
        /// <summary>
        /// Calculate overnight swaps for account/instrument/direction order package.
        /// </summary>
        /// <param name="instrument"></param>
        /// <param name="account"></param>
        /// <param name="accountAssetPair"></param>
        /// <param name="direction"></param>
        /// <param name="orders"></param>
        /// <returns></returns>
        private async Task ProcessOrders(IReadOnlyList <Order> orders, string instrument, IMarginTradingAccount account,
                                         IAccountAssetPair accountAssetPair, OrderDirection direction)
        {
            IReadOnlyList <Order> filteredOrders = orders.ToList();

            //check if swaps had already been taken
            var lastCalcExists = _overnightSwapCache.TryGet(OvernightSwapCalculation.GetKey(account.Id, instrument, direction),
                                                            out var lastCalc) &&
                                 lastCalc.Time >= CalcLastInvocationTime();

            if (lastCalcExists)
            {
                await _log.WriteErrorAsync(nameof(OvernightSwapService), nameof(ProcessOrders),
                                           new Exception($"Overnight swaps had already been taken, filtering: {JsonConvert.SerializeObject(lastCalc)}"), DateTime.UtcNow);

                filteredOrders = orders.Where(x => !lastCalc.OpenOrderIds.Contains(x.Id)).ToList();
            }

            //calc swaps
            var swapRate = direction == OrderDirection.Buy ? accountAssetPair.OvernightSwapLong : accountAssetPair.OvernightSwapShort;

            if (swapRate == 0)
            {
                return;
            }

            var total = filteredOrders.Sum(order => _commissionService.GetOvernightSwap(order, swapRate));

            if (total == 0)
            {
                return;
            }

            //create calculation obj & add to cache
            var volume      = filteredOrders.Select(x => Math.Abs(x.Volume)).Sum();
            var calculation = OvernightSwapCalculation.Create(account.ClientId, account.Id, instrument,
                                                              filteredOrders.Select(order => order.Id).ToList(), _currentStartTimestamp, true, null, volume, total, swapRate, direction);

            //charge comission
            var instrumentName = _assetPairsCache.GetAssetPairByIdOrDefault(accountAssetPair.Instrument)?.Name
                                 ?? accountAssetPair.Instrument;
            await _accountManager.UpdateBalanceAsync(
                account : account,
                amount : -total,
                historyType : AccountHistoryType.Swap,
                comment : $"{instrumentName} {(direction == OrderDirection.Buy ? "long" : "short")} swaps. Volume: {volume}. Positions count: {filteredOrders.Count}. Rate: {swapRate}. Time: {_currentStartTimestamp:u}.",
                auditLog : calculation.ToJson());

            //update calculation state if previous existed
            var newCalcState = lastCalcExists
                                ? OvernightSwapCalculation.Update(calculation, lastCalc)
                                : OvernightSwapCalculation.Create(calculation);

            //add to cache
            _overnightSwapCache.AddOrReplace(newCalcState);

            //write state and log
            await _overnightSwapStateRepository.AddOrReplaceAsync(newCalcState);

            await _overnightSwapHistoryRepository.AddAsync(calculation);
        }