public void Update(StockAnalysis.Share.Bar bar) { double price = BarPriceSelector.Select(bar, _priceSelector); _highest.Update(price); double newHighest = _highest.Value; bool oldBreakout = Breakout; Breakout = Math.Abs(newHighest - price) < 1e-6; CurrentHighest = newHighest; if (Breakout) { // rebreakout is always breakout if (oldBreakout) { // continuous breakout is not rebreakout Rebreakout = false; _intervalSinceLastBreakout = 0; } else { // possible a rebreakout. if (_intervalSinceLastBreakout > 0 && _intervalSinceLastBreakout <= _maxInterval && _intervalSinceLastBreakout >= _minInterval) { Rebreakout = true; IntervalSinceLastBreakout = _intervalSinceLastBreakout; _intervalSinceLastBreakout = 0; } else { Rebreakout = false; _intervalSinceLastBreakout = 0; } } } else { // rebreakout is always breakout Rebreakout = false; if (oldBreakout) { _intervalSinceLastBreakout = 1; } else { if (_intervalSinceLastBreakout > 0) { _intervalSinceLastBreakout++; } } } }
protected override IMetricBooleanExpression BuildExpression() { return(new Comparison( string.Format( "{2}[{0}](BAR.{1}) == BAR.{1}", BreakoutWindow, BarPriceSelector.GetSelectorString(PriceSelector), BreakoutDirection == 0 ? "LO" : "HI"))); }
protected override void ValidateParameterValues() { base.ValidateParameterValues(); if (!BarPriceSelector.IsValidSelector(PriceSelector)) { throw new ArgumentException("价格选择项非法"); } if (MinKeepPeriods < 0) { throw new ArgumentException("获利后保持周期数非法"); } }
protected override void ValidateParameterValues() { base.ValidateParameterValues(); if (!BarPriceSelector.IsValidSelector(PriceSelector)) { throw new ArgumentException("价格选择项非法"); } if (RebreakoutMinInterval <= 0 || RebreakoutMaxInterval <= 0) { throw new ArgumentException("再突破最大/最小时间间隔必须大于零"); } if (RebreakoutMaxInterval > BreakoutWindow) { throw new ArgumentException("再突破最大时间间隔必须小于等于通道突破窗口"); } if (RebreakoutMinInterval > RebreakoutMaxInterval) { throw new ArgumentException("再突破最小时间间隔必须小于等于最大时间间隔"); } }
public override MarketExitingComponentResult ShouldExit(ITradingObject tradingObject) { var result = new MarketExitingComponentResult(); if (Context.ExistsPosition(tradingObject.Code)) { var position = Context.GetPositionDetails(tradingObject.Code).First(); if (position.LastedPeriodCount >= MinKeepPeriods) { var bar = Context.GetBarOfTradingObjectForCurrentPeriod(tradingObject); var price = BarPriceSelector.Select(bar, PriceSelector); if (position.BuyPrice < price) { result.Comments = string.Format("Bailout: buy price {0:0.000}, current price {1:0.000}", position.BuyPrice, price); result.ShouldExit = true; } } } return(result); }
private void UpdateState(Bar bar) { double price = BarPriceSelector.Select(bar, _priceSelector); _highest.Update(price); double highestPrice = _highest.Value; bool breakout = Math.Abs(highestPrice - price) < 1e-6; switch (_state) { case PriceState.Initial: if (breakout) { _state = PriceState.Breakout; LatestBreakoutPrice = highestPrice; LowestPriceAfterBreakout = 0.0; _intervalBetweenLastBreakoutAndRerising = 0; } break; case PriceState.Breakout: if (breakout) { LatestBreakoutPrice = highestPrice; } else { _state = PriceState.Degrading; LowestPriceAfterBreakout = bar.ClosePrice; _intervalBetweenLastBreakoutAndRerising = 1; } break; case PriceState.Degrading: if (bar.ClosePrice <= LowestPriceAfterBreakout) { LowestPriceAfterBreakout = bar.ClosePrice; _intervalBetweenLastBreakoutAndRerising++; } else { if (_intervalBetweenLastBreakoutAndRerising >= _minInterval && _intervalBetweenLastBreakoutAndRerising <= _maxInterval) { _state = PriceState.Rising; } else { ResetState(); } } break; case PriceState.Rising: ResetState(); break; } }