public void MinutePriceAction(TickerReference tickerReference, IPriceBar priceBar) { if (_bars.ContainsKey(tickerReference.Symbol.Id) && _bars[tickerReference.Symbol.Id].ContainsKey(tickerReference.Interval.UnitId)) { UpdatePrice(_bars[tickerReference.Symbol.Id][tickerReference.Interval.UnitId], tickerReference, priceBar); } }
public void LoadPriceBars(Bookmark <IPriceBar> priceBars) { int maxIndex = priceBars.Count; double[] opens = new double[maxIndex]; double[] highs = new double[maxIndex]; double[] lows = new double[maxIndex]; double[] closes = new double[maxIndex]; double[] times = new double[maxIndex]; for (int i = 0; i < maxIndex; i++) { IPriceBar priceBar = priceBars[i]; opens[i] = priceBar.Open; highs[i] = priceBar.High; lows[i] = priceBar.Low; closes[i] = priceBar.Close; times[i] = i; } CandlePlot cp = new CandlePlot(); cp.OpenData = opens; cp.HighData = highs; cp.LowData = lows; cp.CloseData = closes; cp.AbscissaData = times; plotSurface.Clear(); plotSurface.Add(cp); plotSurface.Refresh(); }
private Frame CreateChartFrame(IPriceBar bar, Chart chart) { Frame frame = chart.CreateStandardFrame(bar); int indicatorCount = frame.Indicators.Count; var list = new List <IIndicator>() { new DisplacedMovingAverage(3, 3) { Ordinal = indicatorCount + 1 }, new DetrendedOscillator() { Ordinal = indicatorCount + 2 }, new MACD(8, 17, 9) { Ordinal = indicatorCount + 3 } }; frame.AddIndicators(list); return(frame); }
protected void MinutePriceAction(TickerReference tickerReference, IPriceBar priceBar) { if (MinutePriceBarFeed != null) { MinutePriceBarFeed(tickerReference, priceBar); } }
protected virtual Thrust SetThrustFocus(Chart chart, Thrust thrust) { Frame reactionFrame = chart.Frames.Where(f => f.Bar.time == thrust.SignalTime).FirstOrDefault(); int reactionIndex = chart.Frames.IndexOf(reactionFrame); IPriceBar focusBar = null; double focusPrice = thrust.Direction == EPatternDirection.Up ? reactionFrame.Bar.highMid : reactionFrame.Bar.lowMid; List <Frame> afterFocusFrames = new List <Frame>(); for (int i = reactionIndex + 1; i < chart.Frames.Count; i++) { Frame frame = chart.Frames[i]; if (thrust.Direction == EPatternDirection.Up) { if (frame.Bar.highMid > focusPrice) { thrust.ReactionToFocusSpan = i - reactionIndex; focusBar = frame.Bar; focusPrice = frame.Bar.highMid; afterFocusFrames.Clear(); } else { afterFocusFrames.Add(frame); } } else { if (frame.Bar.lowMid < focusPrice) { thrust.ReactionToFocusSpan = i - reactionIndex; focusBar = frame.Bar; focusPrice = frame.Bar.lowMid; afterFocusFrames.Clear(); } else { afterFocusFrames.Add(frame); } } } // update FocusTime and FocusPrice bool reactionBarIsFocusBar = focusBar == null; thrust.FocusTime = reactionBarIsFocusBar ? reactionFrame.Bar.time : focusBar.time; thrust.FocusPrice = focusPrice; return(thrust); }
public Frame CreateStandardFrame(IPriceBar bar) { var frame = new Frame() { Bar = bar }; var list = new List <IIndicator>() { new SimpleMovingAverage(50) { Ordinal = 1 }, new SimpleMovingAverage(200) { Ordinal = 2 }, }; frame.AddIndicators(list); return(frame); }
public void Write(IPriceBar priceBar) { Write(priceBar.Timestamp, priceBar.Open, priceBar.High, priceBar.Low, priceBar.Close); }
/* * upThrust * traverse >= 10 bars * >= 7 bars have low bid above the 3x3 * >= 5 consecutive bars must have low bid above the 3x3 * sequence may not start with > 3 bars with low bid below 3x3 * if (any of?) top 3 bars of sequence have low bid below 3x3 then lowest low bid of those below the 3x3 must be > .386 ask price * thrust range must be >= (.06 x thrust ReactionPrice) * MACD histogram value of all thrust frames must be > 0 * * downThrust * traverse >= 10 bars * >= 7 bars have low bid above the 3x3 * >= 5 consecutive bars must have low bid above the 3x3 * sequence may not start with > 3 bars with low bid below 3x3 * if (any of?) top 3 bars of sequence have low bid below 3x3 then lowest low bid of those below the 3x3 must be > .386 ask price * thrust range must be >= (.06 x thrust ReactionPrice) * MACD histogram value of all thrust frames must be > 0 * above or below the 3x3? */ #endregion /// <summary> /// Searches the chart for a thrust pattern. /// </summary> /// <param name="chart">Chart object containing at least 20 frames</param> /// <returns>A tradeable thrust object, if found.</returns> protected override Thrust DetectThrust() { Thrust thrust = null; if (_chart.Frames.Count >= 20) { Frame frame; bool upThrustFound = false, downThrustFound = false; short above3x3Count = 0, above3x3Links = 0, below3x3Count = 0, below3x3Links = 0, across3x3Count = 0; Func <short> sequentialAbove3x3Count = () => { return(above3x3Links > 0 ? (short)(above3x3Links + 1) : (short)0); }; Func <short> sequentialBelow3x3Count = () => { return(below3x3Links > 0 ? (short)(below3x3Links + 1) : (short)0); }; AboveBelowDMA previousCandleSide = AboveBelowDMA.Unknown, currentCandleSide = AboveBelowDMA.Unknown; List <AboveBelowDMA> leaderSides = new List <AboveBelowDMA>(); // only need to sniff 20 frames to find thrust // if not in 20 frames, whatever thrust exists has yielded to a consolidation period .. no good short loopCount = 0; while (loopCount < 20) { loopCount++; int i = _chart.Frames.Count - loopCount; frame = _chart.Frames[i]; IPriceBar candle = frame.Bar; IIndicator displaced3x3 = frame.Indicators.First(k => k.Type == IndicatorType.DisplacedMovingAverage && k.ParentOrdinal == 0); if (candle.lowMid >= displaced3x3.Value) { above3x3Count++; if (previousCandleSide == AboveBelowDMA.Above) { above3x3Links++; } currentCandleSide = previousCandleSide = AboveBelowDMA.Above; } else if (candle.highMid <= displaced3x3.Value) { below3x3Count++; if (previousCandleSide == AboveBelowDMA.Below) { below3x3Links++; } currentCandleSide = previousCandleSide = AboveBelowDMA.Below; } else { across3x3Count++; currentCandleSide = previousCandleSide = AboveBelowDMA.Across; } // save the first 3 bar sides if (leaderSides.Count < 3) { leaderSides.Add(currentCandleSide); } // start thrust parsing once 10 bars have been examined if (loopCount > 9) { upThrustFound = sequentialAbove3x3Count() >= 6 && sequentialBelow3x3Count() <= 3 && CheckLeaders(leaderSides, AboveBelowDMA.Above) && !Displaced3x3HasDoubleDip(i, EPatternDirection.Up); downThrustFound = sequentialBelow3x3Count() >= 6 && sequentialAbove3x3Count() <= 3 && CheckLeaders(leaderSides, AboveBelowDMA.Below) && !Displaced3x3HasDoubleDip(i, EPatternDirection.Down); if (upThrustFound || downThrustFound) { EPatternDirection direction = upThrustFound ? EPatternDirection.Up : EPatternDirection.Down; Frame reactionFrame = FindReactionFrame(frame, i, direction); if (reactionFrame != null) { int checkAcrossIndex = GetCheckAcrossIndex(reactionFrame, direction); AboveBelowDMA checkAcrossSide = upThrustFound ? AboveBelowDMA.Above : AboveBelowDMA.Below; if (CheckAcrossFrames(checkAcrossIndex, checkAcrossSide)) { thrust = BuildThrust(reactionFrame, direction); } } break; } } } } return(thrust); }
/// <summary> /// Finds the reaction frame of a detected thrust /// </summary> /// <param name="pilotFrame">Frame at which a valid thrust was confirmed</param> /// <param name="frameIndex">The _chart index of the pilot frame</param> /// <param name="direction">The direction of the confirmed thrust</param> /// <returns>The reaction frame of the thrust</returns> protected virtual Frame FindReactionFrame(Frame pilotFrame, int frameIndex, EPatternDirection direction) { #region reaction frame logic /// for up thrust /// tentative rxn frame is the one with lowBid < 3x3 and 2 preceding candles has a higher chained lowBid /// do a forward search of the chart bars to confirm the rxn frame has lowest lowBid /// the confirmed reaction frame is the one with the lowest lowBid /// for down thrust /// tentative rxn frame is the one with highBid > 3x3 and 2 preceding candles has a lower chained highBid /// do a forward search of the chart bars to confirm the rxn frame has highest highBid /// the confirmed reaction frame is the one with the highest highBid /// do not sweat the breakouts from consolidation (see type G in notes) /// these should yield deeper rxn at worst meaning a missed trade /// the timekill of the trade will mop these up #endregion // find reaction candle Frame horizonFrame = pilotFrame; IPriceBar horizonCandle = horizonFrame.Bar; bool horizonFrameConfirmed = false; while (!horizonFrameConfirmed) { Frame precedingFrame = _chart.Frames[frameIndex - 1]; IPriceBar precedingCandle01 = _chart.Frames[frameIndex - 1].Bar; IPriceBar precedingCandle02 = _chart.Frames[frameIndex - 2].Bar; IIndicator horizon3x3 = horizonFrame.Indicators.First(k => k.Type == IndicatorType.DisplacedMovingAverage); if (direction == EPatternDirection.Up) { if (horizonCandle.lowMid < horizon3x3.Value && precedingCandle01.lowMid > horizonCandle.lowMid && precedingCandle02.lowMid > precedingCandle01.lowMid) { horizonFrameConfirmed = true; } } if (direction == EPatternDirection.Down) { if (horizonCandle.highMid > horizon3x3.Value && precedingCandle01.highMid < horizonCandle.highMid && precedingCandle02.highMid < precedingCandle01.highMid) { horizonFrameConfirmed = true; } } if (!horizonFrameConfirmed) { horizonFrame = precedingFrame; horizonCandle = precedingCandle01; frameIndex--; } } // forward search to confirm rxn frame Frame reactionFrame = horizonFrame; for (int i = frameIndex; i < _chart.Frames.Count; i++) { Frame currentFrame = _chart.Frames[i]; if (direction == EPatternDirection.Up) { if (currentFrame.Bar.lowMid <= reactionFrame.Bar.lowMid) { reactionFrame = currentFrame; } } else { if (currentFrame.Bar.highMid >= reactionFrame.Bar.highMid) { reactionFrame = currentFrame; } } } return(reactionFrame); }
/* * upThrust * traverse >= 10 bars * >= 7 bars have low bid above the 3x3 * >= 5 consecutive bars must have low bid above the 3x3 * sequence may not start with > 3 bars with low bid below 3x3 * if (any of?) top 3 bars of sequence have low bid below 3x3 then lowest low bid of those below the 3x3 must be > .386 ask price * thrust range must be >= (.06 x thrust ReactionPrice) * MACD histogram value of all thrust frames must be > 0 * * downThrust * traverse >= 10 bars * >= 7 bars have low bid above the 3x3 * >= 5 consecutive bars must have low bid above the 3x3 * sequence may not start with > 3 bars with low bid below 3x3 * if (any of?) top 3 bars of sequence have low bid below 3x3 then lowest low bid of those below the 3x3 must be > .386 ask price * thrust range must be >= (.06 x thrust ReactionPrice) * MACD histogram value of all thrust frames must be > 0 * above or below the 3x3? */ #endregion /// <summary> /// Searches the chart for a thrust pattern. /// </summary> /// <param name="chart">Chart object containing at least 20 frames</param> /// <returns>A tradeable thrust object, if found.</returns> protected override Thrust DetectThrust() { Thrust thrust = null; if (_chart.Frames.Count >= 20) { Frame frame; bool upThrustFound = false, downThrustFound = false; short above3x3Count = 0, below3x3Count = 0, across3x3Count = 0; AboveBelowDMA currentCandleSide = AboveBelowDMA.Unknown; List <AboveBelowDMA> leaderSides = new List <AboveBelowDMA>(); List <Frame> acrossFrames = new List <Frame>(); // only need to sniff 20 frames to find thrust // if not in 20 frames, whatever thrust exists has yielded to a consolidation period .. no good for (int loopCount = 1; true; loopCount++) { int i = _chart.Frames.Count - loopCount; frame = _chart.Frames[i]; IPriceBar candle = frame.Bar; IIndicator displaced3x3 = frame.Indicators.First(k => k.Type == IndicatorType.DisplacedMovingAverage && k.ParentOrdinal == 0); if (candle.lowMid >= displaced3x3.Value) { above3x3Count++; currentCandleSide = AboveBelowDMA.Above; } else if (candle.highMid <= displaced3x3.Value) { below3x3Count++; currentCandleSide = AboveBelowDMA.Below; } else { across3x3Count++; currentCandleSide = AboveBelowDMA.Across; acrossFrames.Add(frame); } // save the first 3 bar sides if (leaderSides.Count < 3) { leaderSides.Add(currentCandleSide); } // start thrust parsing once 10 bars have been examined if (loopCount == 7) { upThrustFound = above3x3Count >= 5 && below3x3Count == 0 && CheckLeaders(leaderSides, AboveBelowDMA.Above) && CheckAcrossFrames(acrossFrames, AboveBelowDMA.Above); downThrustFound = below3x3Count >= 5 && above3x3Count == 0 && CheckLeaders(leaderSides, AboveBelowDMA.Below) && CheckAcrossFrames(acrossFrames, AboveBelowDMA.Below); if (upThrustFound || downThrustFound) { EPatternDirection direction = upThrustFound ? EPatternDirection.Up : EPatternDirection.Down; Frame reactionFrame = FindReactionFrame(frame, i, direction); if (reactionFrame != null) { int checkAcrossIndex = GetCheckAcrossIndex(reactionFrame, direction); AboveBelowDMA checkAcrossSide = upThrustFound ? AboveBelowDMA.Above : AboveBelowDMA.Below; if (CheckAcrossFrames(checkAcrossIndex, checkAcrossSide)) { thrust = BuildThrust(reactionFrame, direction); } } } break; } } } return(thrust); }
public override void UpdatePrice(RenkoBars bars, TickerReference tickerReference, IPriceBar priceBar) { bars.Write(priceBar.Timestamp, priceBar.Close); }
public abstract void UpdatePrice(TBars bars, TickerReference tickerReference, IPriceBar priceBar);
public void PriceAction(TickerReference tickerReference, IPriceBar priceBar) { throw new NotImplementedException(); }
public override void UpdatePrice(OHLCBars bars, TickerReference tickerReference, IPriceBar priceBar) { bars.Write(priceBar); }
public new void MinutePriceAction(TickerReference tickerReference, IPriceBar priceBar) { base.MinutePriceAction(tickerReference, priceBar); }
private void PriceBarPriceActionItem(TickerReference tickerReference, IPriceBar priceBar) { Probe.Evaluate(priceBar.Timestamp, priceBar.Close); }
private void MinutePriceBarFeed(TickerReference tickerReference, IPriceBar priceBar) { OHLC.Aggregator.MinutePriceAction(tickerReference, priceBar); PriceBar.Aggregator.MinutePriceAction(tickerReference, priceBar); }
/// <summary> /// Handler for OANDA rate data received from data stream. /// </summary> /// <param name="data">The price tick data received.</param> protected virtual void OnRateReceived(RateStreamResponse data) { if (!data.IsHeartbeat()) { if (_chartsInitialized) { string instrument = data.tick.instrument; Chart instrumentChart = _charts.FirstOrDefault(c => c.Value.Instrument == instrument).Value; IPriceBar lastFrameBar = instrumentChart.Frames.Last().Bar; double bidPrice = data.tick.bid; double askPrice = data.tick.ask; double midPrice = (data.tick.ask - data.tick.bid) / 2; if (Convert.ToDateTime(data.tick.time).ToUniversalTime() < instrumentChart.CreateNewFrameTime) { lastFrameBar.volume++; lastFrameBar.closeBid = bidPrice; lastFrameBar.closeAsk = askPrice; lastFrameBar.closeMid = midPrice; if (lastFrameBar.closeBid <= lastFrameBar.lowBid) { lastFrameBar.lowBid = lastFrameBar.closeBid; } if (lastFrameBar.closeAsk <= lastFrameBar.lowAsk) { lastFrameBar.lowAsk = lastFrameBar.closeAsk; } if (lastFrameBar.closeMid <= lastFrameBar.lowMid) { lastFrameBar.lowMid = lastFrameBar.closeMid; } if (lastFrameBar.closeBid >= lastFrameBar.highBid) { lastFrameBar.highBid = lastFrameBar.closeBid; } if (lastFrameBar.closeAsk >= lastFrameBar.highAsk) { lastFrameBar.highAsk = lastFrameBar.closeAsk; } if (lastFrameBar.closeMid >= lastFrameBar.highMid) { lastFrameBar.highMid = lastFrameBar.closeMid; } } else { lastFrameBar.complete = true; PriceBar newBar = new PriceBar() { time = MAOE.Utilities.GetTimeAsXmlSerializedUtc(instrumentChart.CreateNewFrameTime.Value), openBid = bidPrice, highBid = bidPrice, lowBid = bidPrice, closeBid = bidPrice, openAsk = askPrice, highAsk = askPrice, lowAsk = askPrice, closeAsk = askPrice, openMid = midPrice, highMid = midPrice, lowMid = midPrice, closeMid = midPrice, volume = 1 }; instrumentChart.Frames.Add(CreateChartFrame(newBar, instrumentChart)); } } MAOE.Utilities.ReleaseTick(); } }
/// <summary> /// /// </summary> /// <param name="chart"></param> /// <param name="thrust"></param> /// <param name="retracement"></param> protected virtual async void ManageOrder(Chart chart, Thrust thrust) { StrategyTransaction[] transactions = null; StrategyTransaction orderTransaction, fillTransaction, cancelTransaction, exitTransaction; // get transaction collection from db int orderTransactionID = thrust.StrategyTransactionID.GetValueOrDefault(); transactions = await StrategyCaller.Instance().GetStrategyTransactionsCollectionAsync(orderTransactionID); orderTransaction = transactions.FirstOrDefault(t => t.StrategyTransactionID == orderTransactionID); fillTransaction = transactions.FirstOrDefault(t => t.BrokerOrderID != null && t.Type == MACC.Constants.TransactionTypes.OrderFilled); cancelTransaction = transactions.FirstOrDefault(t => t.BrokerOrderID != null && t.Type == MACC.Constants.TransactionTypes.OrderCancel); exitTransaction = transactions.FirstOrDefault(t => t.BrokerTradeID != null && t.Type != MACC.Constants.TransactionTypes.TradeUpdate); bool purgeInActiveThrust = true; if (fillTransaction == null) { if (cancelTransaction != null) { // order cancelled thrust.Active = false; } else { // order open if (!thrust.Active) { // cancel the order // the cancel transaction will be written to the db by the event stream handler await Rest.DeleteOrderAsync(_accountId, Convert.ToInt64(orderTransaction.BrokerTransactionID)); } else { if (thrust.FocusChanged() || (thrust.FillZoneReached() && thrust.TakeProfitZoneReached())) { AddAlgorithmMessage(string.Format("UPDATE ORDER: {0}: FCH-{1}: FZR-{2}: TPR-{3}", orderTransaction.Instrument, thrust.FocusChanged(), thrust.FillZoneReached(), thrust.TakeProfitZoneReached())); UpdateEntryOrder(orderTransaction, chart, thrust); } } } } else { if (exitTransaction == null) { // order filled purgeInActiveThrust = false; FibonacciRetracement retracement = (FibonacciRetracement)thrust.Study; #region get open trade info long tradeId = Convert.ToInt64(fillTransaction.BrokerTransactionID); Frame fillFrame = chart.Frames.LastOrDefault(f => Convert.ToDateTime(f.Bar.time).ToUniversalTime() <= fillTransaction.Time); int fillIndex = chart.Frames.IndexOf(fillFrame); #endregion #region get takeProfitPrice and stopLossPrice int profitWaitPeriods = Parameters.GetInteger("thrustProfitWaitPeriods") ?? 6; thrust.ProfitWindowClosed = (fillIndex + profitWaitPeriods) < chart.Frames.Count; IPriceBar lastBar = chart.Frames.Last().Bar; bool hasProfit = orderTransaction.Side == MACC.Constants.SignalSide.Buy ? lastBar.closeMid > fillTransaction.Price : lastBar.closeMid < fillTransaction.Price; #region stopLossPrice & takeProfitPrice logic // adjust stopLossPrice and takeProfitPrice // if a buy ... // move the stop to the lower of the .500 fib price or [patern lowMid price set by the post-fill price action] // move the profit target to 1 or 2 pips under .618 * (thrust.FocusPrice - [pattern lowMid price set by the post-fill price action]) // if a sell ... // move the stop to the higher of the .500 fib price or [patern highMid price set by the post-fill price action] // move the profit target to 1 or 2 pips above .618 * ([pattern lowMid price set by the post-fill price action] - thrust.FocusPrice) #endregion double?takeProfitPrice = GetAdjustedTakeProfitPrice(chart, thrust.Side, retracement); AddAlgorithmMessage(string.Format("GET SLP: {0}: TPZ-{1}: PWC-{2}: XTP-{3}: CLP-{4}: PFT-{5}", fillTransaction.Instrument, thrust.TakeProfitZoneReached(), thrust.ProfitWindowClosed, retracement.ExtremaPrice, lastBar.closeMid, hasProfit)); double?stopLossPrice = GetAdjustedStopLossPrice(chart, thrust.Side, thrust, hasProfit); #endregion #region kill or update the trade // not profitable && beyond r500 .. kill it if (stopLossPrice.GetValueOrDefault() == -1) { thrust.Active = false; purgeInActiveThrust = true; try { await Rest.DeleteTradeAsync(_accountId, tradeId); } catch (Exception e) { AddAlgorithmMessage(string.Format("CLOSE TRADE {0} Failed: {1}", tradeId, e.Message), true, TraceEventType.Error); } } else { if ((takeProfitPrice ?? thrust.TakeProfitPrice) != thrust.TakeProfitPrice || (stopLossPrice ?? thrust.StopLossPrice) != thrust.StopLossPrice) { AddAlgorithmMessage(string.Format("UPDATE TRADE: {0}: TPZ-{1}: PWC-{2}: XTP-{3}: CLP-{4}: TP-{5}: TTP-{6}: SL-{7}: TSL-{8}", fillTransaction.Instrument, thrust.TakeProfitZoneReached(), thrust.ProfitWindowClosed, retracement.ExtremaPrice, lastBar.closeMid, takeProfitPrice, thrust.TakeProfitPrice, stopLossPrice, thrust.StopLossPrice)); UpdateOpenTrade(thrust, tradeId, takeProfitPrice, stopLossPrice, retracement.LevelPlaces()); } } #endregion } else { // trade closed #region about closed trades // if coll includes a stopLossFilled or takeProfitFilled .. // set thrust.Active = false // this be done server side when the strategyTransaction from the stream is saved // the signal should be found on the server and signal.Active should be set to false // do it here also #endregion thrust.Active = false; } } if (!thrust.Active && purgeInActiveThrust) { await PurgeThrust(chart, thrust); } }