Esempio n. 1
0
        public void ValidateInstrumentPositionVolume(IAccountAssetPair assetPair, Order order)
        {
            var existingPositionsVolume = _ordersCache.ActiveOrders.GetOrdersByInstrumentAndAccount(assetPair.Instrument, order.AccountId).Sum(o => o.Volume);

            if (assetPair.PositionLimit > 0 && Math.Abs(existingPositionsVolume + order.Volume) > assetPair.PositionLimit)
            {
                throw new ValidateOrderException(OrderRejectReason.InvalidVolume,
                                                 $"Margin Trading is in beta testing. The volume of the net open position is temporarily limited to {assetPair.PositionLimit} {assetPair.Instrument}. Thank you for using Lykke Margin Trading, the limit will be cancelled soon!");
            }
        }
Esempio n. 2
0
        public async Task <IAccountAssetPair> AddOrReplaceAccountAssetAsync(IAccountAssetPair model)
        {
            await _pairsRepository.AddOrReplaceAsync(model);

            await UpdateAccountAssetsCache();

            await _clientNotifyService.NotifyTradingConditionsChanged(model.TradingConditionId);

            return(model);
        }
Esempio n. 3
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. 4
0
 public static AccountAssetPairModel ToBackendContract(this IAccountAssetPair src)
 {
     return(new AccountAssetPairModel
     {
         TradingConditionId = src.TradingConditionId,
         BaseAssetId = src.BaseAssetId,
         Instrument = src.Instrument,
         LeverageInit = src.LeverageInit,
         LeverageMaintenance = src.LeverageMaintenance,
         SwapLong = src.SwapLong,
         SwapShort = src.SwapShort,
         OvernightSwapLong = src.OvernightSwapLong,
         OvernightSwapShort = src.OvernightSwapShort,
         CommissionLong = src.CommissionLong,
         CommissionShort = src.CommissionShort,
         CommissionLot = src.CommissionLot,
         DeltaBid = src.DeltaBid,
         DeltaAsk = src.DeltaAsk,
         DealLimit = src.DealLimit,
         PositionLimit = src.PositionLimit
     });
 }
 public static AccountAssetPairEntity Create(IAccountAssetPair src)
 {
     return(new AccountAssetPairEntity
     {
         PartitionKey = GeneratePartitionKey(src.TradingConditionId, src.BaseAssetId),
         RowKey = GenerateRowKey(src.Instrument),
         TradingConditionId = src.TradingConditionId,
         BaseAssetId = src.BaseAssetId,
         LeverageInit = src.LeverageInit,
         LeverageMaintenance = src.LeverageMaintenance,
         SwapLong = (double)src.SwapLong,
         SwapShort = (double)src.SwapShort,
         OvernightSwapLong = (double)src.OvernightSwapLong,
         OvernightSwapShort = (double)src.OvernightSwapShort,
         CommissionLong = (double)src.CommissionLong,
         CommissionShort = (double)src.CommissionShort,
         CommissionLot = (double)src.CommissionLot,
         DeltaBid = (double)src.DeltaBid,
         DeltaAsk = (double)src.DeltaAsk,
         DealLimit = (double)src.DealLimit,
         PositionLimit = (double)src.PositionLimit
     });
 }
Esempio n. 6
0
 private AccountAssetPairContract Convert(IAccountAssetPair accountAssetPair)
 {
     return(_convertService.Convert <IAccountAssetPair, AccountAssetPairContract>(accountAssetPair));
 }
Esempio n. 7
0
 private AccountAssetPairContract Convert(IAccountAssetPair settings)
 {
     return(_convertService.Convert <IAccountAssetPair, AccountAssetPairContract>(settings));
 }
 public async Task AddOrReplaceAsync(IAccountAssetPair accountAssetPair)
 {
     await _tableStorage.InsertOrReplaceAsync(AccountAssetPairEntity.Create(accountAssetPair));
 }
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);
        }