/// <summary> /// Genrate output based on input data /// </summary> protected virtual IPointModel Parse(dynamic input) { var props = input.Split(" "); long.TryParse(props[0], out long dateTime); double.TryParse(props[1], out double bid); double.TryParse(props[2], out double bidSize); double.TryParse(props[3], out double ask); double.TryParse(props[4], out double askSize); var response = new PointModel { Time = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(dateTime), Ask = ask, Bid = bid, Last = ask, AskSize = askSize, BidSize = bidSize }; if (ConversionManager.Compare(askSize, 0)) { response.Last = bid; } return(response); }
/// <summary> /// Process incoming quotes /// </summary> /// <param name="input"></param> protected void OnInputQuote(InputPointModel input) { var dateAsk = input.AskDate; var dateBid = input.BidDate; var currentAsk = input.Ask; var currentBid = input.Bid; var previousAsk = _point?.Ask ?? currentAsk; var previousBid = _point?.Bid ?? currentBid; var symbol = input.Symbol; var point = new PointModel { Ask = currentAsk, Bid = currentBid, Bar = new PointBarModel(), Instrument = Account.Instruments[symbol], AskSize = input.AskSize, BidSize = input.BidSize, Time = DateTimeOffset.FromUnixTimeMilliseconds(Math.Max(dateAsk.Value, dateBid.Value)).DateTime, Last = ConversionManager.Compare(currentBid, previousBid) ? currentAsk : currentBid }; _point = point; UpdatePointProps(point); }
/// <summary> /// Process incoming quotes /// </summary> /// <param name="input"></param> protected void OnInputQuote(dynamic input) { var dateAsk = ConversionManager.To <long>(input.askdate); var dateBid = ConversionManager.To <long>(input.biddate); var currentAsk = ConversionManager.To <double>(input.ask); var currentBid = ConversionManager.To <double>(input.bid); var previousAsk = _point?.Ask ?? currentAsk; var previousBid = _point?.Bid ?? currentBid; var symbol = $"{ input.symbol }"; var point = new PointModel { Ask = currentAsk, Bid = currentBid, Bar = new PointBarModel(), Instrument = Account.Instruments[symbol], AskSize = ConversionManager.To <double>(input.asksz), BidSize = ConversionManager.To <double>(input.bidsz), Time = DateTimeOffset.FromUnixTimeMilliseconds(Math.Max(dateAsk, dateBid)).DateTime, Last = ConversionManager.Compare(currentBid, previousBid) ? currentAsk : currentBid }; _point = point; UpdatePointProps(point); }
/// <summary> /// Calculate single value /// </summary> /// <param name="collection"></param> /// <returns></returns> public override RelativeStrengthIndicator Calculate(IIndexCollection <IPointModel> collection) { var currentPoint = collection.ElementAtOrDefault(collection.Count - 1); if (currentPoint == null) { return(this); } var positives = new List <double>(Interval); var negatives = new List <double>(Interval); for (var i = 1; i <= Interval; i++) { var nextPrice = collection.ElementAtOrDefault(collection.Count - i); var previousPrice = collection.ElementAtOrDefault(collection.Count - i - 1); if (nextPrice != null && previousPrice != null) { positives.Add(Math.Max(nextPrice.Bar.Close.Value - previousPrice.Bar.Close.Value, 0.0)); negatives.Add(Math.Max(previousPrice.Bar.Close.Value - nextPrice.Bar.Close.Value, 0.0)); } } var averagePositive = CalculationManager.SimpleAverage(positives, positives.Count - 1, Interval); var averageNegative = CalculationManager.SimpleAverage(negatives, negatives.Count - 1, Interval); var average = ConversionManager.Compare(averageNegative, 0) ? 1.0 : averagePositive / averageNegative; var nextValue = 100.0 - 100.0 / (1.0 + average); var nextIndicatorPoint = new PointModel { Time = currentPoint.Time, TimeFrame = currentPoint.TimeFrame, Last = nextValue, Bar = new PointBarModel { Close = nextValue } }; var previousIndicatorPoint = Values.ElementAtOrDefault(collection.Count - 1); if (previousIndicatorPoint == null) { Values.Add(nextIndicatorPoint); } Values[collection.Count - 1] = nextIndicatorPoint; currentPoint.Series[Name] = currentPoint.Series.TryGetValue(Name, out IPointModel seriesItem) ? seriesItem : new RelativeStrengthIndicator(); currentPoint.Series[Name].Bar.Close = currentPoint.Series[Name].Last = nextIndicatorPoint.Bar.Close; currentPoint.Series[Name].Time = currentPoint.Time; currentPoint.Series[Name].ChartData = ChartData; Last = Bar.Close = currentPoint.Series[Name].Bar.Close; return(this); }
/// <summary> /// Create position when there is a position with the same transaction type /// </summary> /// <param name="nextOrder"></param> /// <param name="previousPosition"></param> /// <returns></returns> protected virtual ITransactionPositionModel DecreasePosition(ITransactionOrderModel nextOrder, ITransactionPositionModel previousPosition) { if (previousPosition == null) { return(null); } var isSameBuy = Equals(previousPosition.Side, OrderSideEnum.Buy) && Equals(nextOrder.Side, OrderSideEnum.Buy); var isSameSell = Equals(previousPosition.Side, OrderSideEnum.Sell) && Equals(nextOrder.Side, OrderSideEnum.Sell); if (isSameBuy || isSameSell) { return(null); } var openPrices = GetOpenPrices(nextOrder); var pointModel = nextOrder.Instrument.PointGroups.LastOrDefault(); nextOrder.Time = pointModel.Time; nextOrder.Price = openPrices.Last().Price; nextOrder.Status = OrderStatusEnum.Filled; var nextPosition = UpdatePositionProps(new TransactionPositionModel(), nextOrder); nextPosition.Time = pointModel.Time; nextPosition.OpenPrices = openPrices; nextPosition.Price = nextPosition.OpenPrice = nextOrder.Price; nextPosition.Size = Math.Abs(nextPosition.Size.Value - previousPosition.Size.Value); previousPosition.CloseTime = nextPosition.Time; previousPosition.ClosePrice = nextPosition.OpenPrice; previousPosition.GainLoss = previousPosition.GainLossEstimate; previousPosition.GainLossPoints = previousPosition.GainLossPointsEstimate; Account.Balance += previousPosition.GainLoss; Account.ActiveOrders.Remove(nextOrder); Account.ActivePositions.Remove(previousPosition); DeleteOrders(previousPosition.Orders.ToArray()); Account.Orders.Add(nextOrder); Account.Positions.Add(previousPosition); if (ConversionManager.Compare(nextPosition.Size, 0.0) == false) { Account.ActivePositions.Add(nextPosition); } return(nextPosition); }
/// <summary> /// Calculate single value /// </summary> /// <param name="collection"></param> /// <returns></returns> public override MovingAverageIndicator Calculate(IIndexCollection <IPointModel> collection) { var currentPoint = collection.ElementAtOrDefault(collection.Count - 1); if (currentPoint == null) { return(this); } var pointPrice = currentPoint.Bar.Close; switch (Mode) { case MovingAverageEnum.Bid: pointPrice = currentPoint.Bid; break; case MovingAverageEnum.Ask: pointPrice = currentPoint.Ask; break; } var nextIndicatorPoint = new PointModel { Last = pointPrice, Time = currentPoint.Time, TimeFrame = currentPoint.TimeFrame, Bar = new PointBarModel { Close = pointPrice } }; var previousIndicatorPoint = Values.ElementAtOrDefault(collection.Count - 1); if (previousIndicatorPoint == null) { Values.Add(nextIndicatorPoint); } Values[collection.Count - 1] = nextIndicatorPoint; var average = CalculationManager.LinearWeightAverage(Values.Select(o => o.Bar.Close.Value), Values.Count - 1, Interval); currentPoint.Series[Name] = currentPoint.Series.TryGetValue(Name, out IPointModel seriesItem) ? seriesItem : new MovingAverageIndicator(); currentPoint.Series[Name].Bar.Close = currentPoint.Series[Name].Last = ConversionManager.Compare(average, 0) ? nextIndicatorPoint.Bar.Close : average; currentPoint.Series[Name].Time = currentPoint.Time; currentPoint.Series[Name].ChartData = ChartData; Last = Bar.Close = currentPoint.Series[Name].Bar.Close; return(this); }
/// <summary> /// Calculate indicator value /// </summary> /// <param name="collection"></param> /// <returns></returns> public override ScaleIndicator Calculate(IIndexCollection <IPointModel> collection) { var currentPoint = collection.ElementAtOrDefault(collection.Count - 1); if (currentPoint == null || currentPoint.Series == null) { return(this); } var pointValue = currentPoint.Bar.Close ?? 0.0; _min = _min == null ? pointValue : Math.Min(_min.Value, pointValue); _max = _max == null ? pointValue : Math.Max(_max.Value, pointValue); var nextValue = ConversionManager.Compare(_min, _max) ? 0.0 : Min + (pointValue - _min.Value) * (Max - Min) / (_max.Value - _min.Value); var nextIndicatorPoint = new PointModel { Time = currentPoint.Time, TimeFrame = currentPoint.TimeFrame, Last = nextValue, Bar = new PointBarModel { Close = nextValue } }; var previousIndicatorPoint = Values.ElementAtOrDefault(collection.Count - 1); if (previousIndicatorPoint == null) { Values.Add(nextIndicatorPoint); } Values[collection.Count - 1] = nextIndicatorPoint; currentPoint.Series[Name] = currentPoint.Series.TryGetValue(Name, out IPointModel seriesItem) ? seriesItem : new ScaleIndicator(); currentPoint.Series[Name].Bar.Close = currentPoint.Series[Name].Last = CalculationManager.LinearWeightAverage(Values.Select(o => o.Bar.Close.Value), Values.Count - 1, Interval); currentPoint.Series[Name].Time = currentPoint.Time; currentPoint.Series[Name].ChartData = ChartData; Last = Bar.Close = currentPoint.Series[Name].Bar.Close; return(this); }
/// <summary> /// Define open price based on order /// </summary> /// <param name="nextOrder"></param> protected virtual IList <ITransactionOrderModel> GetOpenPrices(ITransactionOrderModel nextOrder) { var openPrice = nextOrder.Price; var pointModel = nextOrder.Instrument.PointGroups.LastOrDefault(); if (ConversionManager.Compare(openPrice ?? 0.0, 0.0)) { openPrice = Equals(nextOrder.Side, OrderSideEnum.Buy) ? pointModel.Ask : pointModel.Bid; } return(new List <ITransactionOrderModel> { new TransactionOrderModel { Price = openPrice, Size = nextOrder.Size, Time = pointModel.Time } }); }
public void ShouldCalculateKestnerRatio() { var inputs = new List <double> { 2.0, 5.0, 15.0, 35.0, 20.0, 55.0, 150.0 }; var logs = inputs .Select(o => Math.Log(o)) .Where(o => double.IsInfinity(o) == false && ConversionManager.Compare(o, 0) == false) .ToList(); var count = logs.Count; var deviation = 0.0; var regression = new double[count]; var slope = Math.Log(inputs.Last()) / count; for (var i = 0; i < count; i++) { var v = inputs.ElementAtOrDefault(i); var log = Math.Log(v); if (double.IsNaN(log) == false) { regression[i] = regression.ElementAtOrDefault(i - 1) + slope; deviation += Math.Pow(regression[i] - log, 2); } } var error = Math.Sqrt(deviation / count) / Math.Sqrt(count); var expectation = slope / (error * count); var deals = inputs.Select((o, i) => new InputData { Value = o }); var kestnerRatio = new KestnerRatio { Values = deals }; var ratio = kestnerRatio.Calculate(); Assert.Equal(expectation, ratio, 2); }
/// <summary> /// Process incoming quotes /// </summary> /// <param name="input"></param> protected void OnInputData(InputPointModel input) { var currentAsk = input.Ask; var currentBid = input.Bid; var previousAsk = _point?.Ask ?? currentAsk; var previousBid = _point?.Bid ?? currentBid; var instrument = $"{ input.Instrument }"; var point = new PointModel { Ask = currentAsk, Bid = currentBid, Time = input.Time, Bar = new PointBarModel(), Instrument = Account.Instruments[instrument], Last = ConversionManager.Compare(currentBid, previousBid) ? currentAsk : currentBid }; if (input.Asks.Any()) { var edge = input.Asks.Min(o => new { o.Price, o.Size }); point.Ask = Math.Min(point.Ask.Value, edge.Price.Value); point.AskSize = edge.Size; } if (input.Bids.Any()) { var edge = input.Bids.Max(o => new { o.Price, o.Size }); point.Bid = Math.Max(point.Bid.Value, edge.Price.Value); point.BidSize = edge.Size; } _point = point; UpdatePointProps(point); }
/// <summary> /// Convert abstract order to a real one /// </summary> /// <param name="internalOrder"></param> /// <param name="orderClass"></param> /// <returns></returns> //protected async Task<ITransactionOrderModel> CreateOrder(ITransactionOrderModel internalOrder, dynamic orderClass = null) //{ // var size = ConversionManager.To<long>(internalOrder.Size); // var price = ConversionManager.To<decimal>(internalOrder.Price); // var span = MapInput.GetTimeSpan(internalOrder.TimeSpan.Value).Value; // var orderSide = MapInput.GetOrderSide(internalOrder.Side.Value).Value; // var orderType = MapInput.GetOrderType(internalOrder.Type.Value).Value; // var activationPrice = ConversionManager.To<decimal>(internalOrder.ActivationPrice); // var orderQuery = new NewOrderRequest(internalOrder.Instrument.Name, size, orderSide, orderType, span) // { // ClientOrderId = internalOrder.Id // }; // if (orderClass != null) // { // orderQuery.OrderClass = orderClass; // } // switch (orderType) // { // case OrderType.Stop: orderQuery.StopPrice = price; break; // case OrderType.Limit: orderQuery.LimitPrice = price; break; // case OrderType.StopLimit: orderQuery.StopPrice = activationPrice; orderQuery.LimitPrice = price; break; // } // await _executionClient.PostOrderAsync(orderQuery); // foreach (var childData in internalOrder.Orders) // { // await CreateOrder(childData); // } // return internalOrder; //} /// <summary> /// Load account data /// </summary> /// <returns></returns> //protected async Task GetAccountData() //{ // var account = await _executionClient.GetAccountAsync(); // Account.Leverage = account.Multiplier; // Account.Currency = account.Currency.ToUpper(); // Account.Balance = ConversionManager.To<double>(account.Equity); // Account.InitialBalance = ConversionManager.To<double>(account.LastEquity); //} /// <summary> /// Load orders /// </summary> /// <returns></returns> //protected async Task GetOrders() //{ // var orders = await _executionClient.ListOrdersAsync(new ListOrdersRequest // { // LimitOrderNumber = 500, // OrderListSorting = SortDirection.Descending, // OrderStatusFilter = OrderStatusFilter.Closed // }); // foreach (var o in orders) // { // var order = new TransactionOrderModel(); // Account.Instruments.TryGetValue(o.Symbol, out IInstrumentModel instrument); // order.Size = o.Quantity; // order.Time = o.CreatedAtUtc; // order.Id = o.OrderId.ToString(); // order.Type = MapOutput.GetOrderType(o.OrderType); // order.Side = MapOutput.GetOrderSide(o.OrderSide); // order.Status = MapOutput.GetOrderStatus(o.OrderStatus); // order.TimeSpan = MapOutput.GetTimeSpan(o.TimeInForce); // order.Price = ConversionManager.To<double>(o.AverageFillPrice ?? o.StopPrice ?? o.LimitPrice); // order.Instrument = instrument ?? new InstrumentModel // { // Name = o.Symbol // }; // Account.Orders.Add(order); // } //} /// <summary> /// Load active orders /// </summary> /// <returns></returns> //protected async Task GetActiveOrders() //{ // var orders = await _executionClient.ListOrdersAsync(new ListOrdersRequest // { // LimitOrderNumber = 500, // OrderListSorting = SortDirection.Descending, // OrderStatusFilter = OrderStatusFilter.Open // }); // foreach (var o in orders) // { // var order = new TransactionOrderModel(); // Account.Instruments.TryGetValue(o.Symbol, out IInstrumentModel instrument); // order.Size = o.Quantity; // order.Time = o.CreatedAtUtc; // order.Id = o.OrderId.ToString(); // order.Type = MapOutput.GetOrderType(o.OrderType); // order.Side = MapOutput.GetOrderSide(o.OrderSide); // order.Status = MapOutput.GetOrderStatus(o.OrderStatus); // order.TimeSpan = MapOutput.GetTimeSpan(o.TimeInForce); // order.Price = ConversionManager.To<double>(o.AverageFillPrice ?? o.StopPrice ?? o.LimitPrice); // order.Instrument = instrument ?? new InstrumentModel // { // Name = o.Symbol // }; // Account.ActiveOrders.Add(order); // } //} /// <summary> /// Load active positions /// </summary> /// <returns></returns> //protected async Task GetActivePositions() //{ // var positions = await _executionClient.ListPositionsAsync(); // foreach (var o in positions) // { // var position = new TransactionPositionModel(); // Account.Instruments.TryGetValue(o.Symbol, out IInstrumentModel instrument); // position.Size = o.Quantity; // position.Time = DateTime.MinValue; // position.Type = OrderTypeEnum.Market; // position.Side = MapOutput.GetPositionSide(o.Side); // position.OpenPrice = ConversionManager.To<double>(o.AverageEntryPrice); // position.ClosePrice = ConversionManager.To<double>(o.AssetCurrentPrice); // position.GainLoss = ConversionManager.To<double>(o.UnrealizedProfitLoss); // position.GainLossPoints = ConversionManager.To<double>((o.AssetCurrentPrice - o.AverageEntryPrice)) * MapOutput.GetDirection(position.Side.Value); // position.Instrument = instrument ?? new InstrumentModel // { // Name = o.Symbol // }; // position.OpenPrices = new List<ITransactionOrderModel> // { // new TransactionOrderModel // { // Price = position.OpenPrice, // Instrument = position.Instrument // } // }; // Account.ActivePositions.Add(position); // } //} /// <summary> /// Process incoming quotes /// </summary> /// <param name="input"></param> protected void OnInputQuote(dynamic input) { var currentAsk = ConversionManager.To <double>(input.P); var currentBid = ConversionManager.To <double>(input.p); var previousAsk = _point?.Ask ?? currentAsk; var previousBid = _point?.Bid ?? currentBid; var symbol = $"{ input.T }"; var point = new PointModel { Ask = currentAsk, Bid = currentBid, Bar = new PointBarModel(), Instrument = Account.Instruments[symbol], AskSize = ConversionManager.To <double>(input.S), BidSize = ConversionManager.To <double>(input.s), Time = _unixTime.AddTicks(ConversionManager.To <long>(input.t) / 100), Last = ConversionManager.Compare(currentBid, previousBid) ? currentAsk : currentBid }; _point = point; UpdatePointProps(point); }