public void PointCalculationsCorrect() { var value = MarginTradingCalculations.GetVolumeFromPoints(1, 3); Assert.AreEqual(0.001, value); value = MarginTradingCalculations.GetVolumeFromPoints(10, 3); Assert.AreEqual(0.01, value); }
public void ValidateOrderStops(OrderDirection type, BidAskPair quote, decimal deltaBid, decimal deltaAsk, decimal?takeProfit, decimal?stopLoss, decimal?expectedOpenPrice, int assetAccuracy) { var deltaBidValue = MarginTradingCalculations.GetVolumeFromPoints(deltaBid, assetAccuracy); var deltaAskValue = MarginTradingCalculations.GetVolumeFromPoints(deltaAsk, assetAccuracy); if (expectedOpenPrice.HasValue) { decimal minGray; decimal maxGray; //check TP/SL for pending order if (type == OrderDirection.Buy) { minGray = Math.Round(expectedOpenPrice.Value - 2 * deltaBidValue, assetAccuracy); maxGray = Math.Round(expectedOpenPrice.Value + deltaAskValue, assetAccuracy); if (takeProfit.HasValue && takeProfit > 0 && takeProfit < maxGray) { throw new ValidateOrderException(OrderRejectReason.InvalidTakeProfit, string.Format(MtMessages.Validation_TakeProfitMustBeMore, Math.Round((decimal)takeProfit, assetAccuracy), maxGray), $"quote (bid/ask): {quote.Bid}/{quote.Ask}"); } if (stopLoss.HasValue && stopLoss > 0 && stopLoss > minGray) { throw new ValidateOrderException(OrderRejectReason.InvalidStoploss, string.Format(MtMessages.Validation_StopLossMustBeLess, Math.Round((decimal)stopLoss, assetAccuracy), minGray), $"quote (bid/ask): {quote.Bid}/{quote.Ask}"); } } else { minGray = Math.Round(expectedOpenPrice.Value - deltaBidValue, assetAccuracy); maxGray = Math.Round(expectedOpenPrice.Value + 2 * deltaAskValue, assetAccuracy); if (takeProfit.HasValue && takeProfit > 0 && takeProfit > minGray) { throw new ValidateOrderException(OrderRejectReason.InvalidTakeProfit, string.Format(MtMessages.Validation_TakeProfitMustBeLess, Math.Round((decimal)takeProfit, assetAccuracy), minGray), $"quote (bid/ask): {quote.Bid}/{quote.Ask}"); } if (stopLoss.HasValue && stopLoss > 0 && stopLoss < maxGray) { throw new ValidateOrderException(OrderRejectReason.InvalidStoploss, string.Format(MtMessages.Validation_StopLossMustBeMore, Math.Round((decimal)stopLoss, assetAccuracy), maxGray), $"quote (bid/ask): {quote.Bid}/{quote.Ask}"); } } } else { //check TP/SL for market order var minGray = Math.Round(quote.Bid - deltaBidValue, assetAccuracy); var maxGray = Math.Round(quote.Ask + deltaAskValue, assetAccuracy); if (type == OrderDirection.Buy) { if (takeProfit.HasValue && takeProfit > 0 && takeProfit < maxGray) { throw new ValidateOrderException(OrderRejectReason.InvalidTakeProfit, string.Format(MtMessages.Validation_TakeProfitMustBeMore, Math.Round((decimal)takeProfit, assetAccuracy), maxGray), $"quote (bid/ask): {quote.Bid}/{quote.Ask}"); } if (stopLoss.HasValue && stopLoss > 0 && stopLoss > minGray) { throw new ValidateOrderException(OrderRejectReason.InvalidStoploss, string.Format(MtMessages.Validation_StopLossMustBeLess, Math.Round((decimal)stopLoss, assetAccuracy), minGray), $"quote (bid/ask): {quote.Bid}/{quote.Ask}"); } } else { if (takeProfit.HasValue && takeProfit > 0 && takeProfit > minGray) { throw new ValidateOrderException(OrderRejectReason.InvalidTakeProfit, string.Format(MtMessages.Validation_TakeProfitMustBeLess, Math.Round((decimal)takeProfit, assetAccuracy), minGray), $"quote (bid/ask): {quote.Bid}/{quote.Ask}"); } if (stopLoss.HasValue && stopLoss > 0 && stopLoss < maxGray) { throw new ValidateOrderException(OrderRejectReason.InvalidStoploss, string.Format(MtMessages.Validation_StopLossMustBeMore, Math.Round((decimal)stopLoss, assetAccuracy), maxGray), $"quote (bid/ask): {quote.Bid}/{quote.Ask}"); } } } }