Пример #1
0
        /// <summary>
        /// Return the nearest significant support level above or below 'price'.
        /// 'sign' is the direction to look for a level. +1 means above, -1 means below, 0 means either side.
        /// 'min_dist' means the nearest SnR level >= price + sign * min_dist (default: 0 if sign=0, 0.25*MCS if sign=±1)
        /// 'range' is a bound on the levels to check (default: no range limit)
        /// 'radius' is a shortcut for Range(price - radius, price + radius). (Default: ignored) </summary>
        public Level Nearest(QuoteCurrency price, int sign, QuoteCurrency?min_dist = null, RangeF?range = null, QuoteCurrency?radius = null, double?min_strength = 0.5)
        {
            // Set the range
            if (radius != null && range == null)
            {
                range = new RangeF((double)(price - radius), (double)(price + radius));
            }

            // Set the minimum if not provided
            min_dist = min_dist ?? (sign == 0 ? 0 : 0.25 * Instrument.MCS);

            // Get the threshold price
            var thresh = price + sign * min_dist.Value;

            // Find levels above/below the threshold
            var levels = (IEnumerable <Level>)SnRLevels;

            if (range != null)
            {
                levels = levels.Where(x => range.Value.Contains((double)x.Price));
            }
            if (sign != 0)
            {
                levels = levels.Where(x => Math.Sign(x.Price - thresh) == sign);
            }
            if (min_strength != null)
            {
                levels = levels.Where(x => x.Strength >= min_strength.Value);
            }

            // Return the levels closed to 'price'
            return(levels.MinByOrDefault(x => Math.Abs(x.Price - price)));
        }
Пример #2
0
        /// <summary>Single candle type. Relative to the mean candle size (total size)</summary>
        public EType Type(QuoteCurrency mcs)
        {
            // A candle is a doji if the body is very small
            if (BodyLength < 0.03 * mcs)
            {
                return(EType.Doji);
            }

            // A candle is a hammer/inverse hammer if it has a small body that is near one end of the candle
            if (BodyLength < 0.125 * mcs || BodyLength < 0.1 * TotalLength)
            {
                if (UpperWickLength < 0.1 * TotalLength)
                {
                    return(EType.Hammer);
                }
                if (LowerWickLength < 0.1 * TotalLength)
                {
                    return(EType.InvHammer);
                }
                return(EType.SpinningTop);
            }

            // A candle is a Marubozu if it has a large body and is a large portion of the total length
            if (BodyLength > 0.9 * mcs && BodyLength > 0.5 * TotalLength)
            {
                // A strengthening or weakening marubozu
                return
                    (Strengthening ? EType.MarubozuStrengthening :
                     Weakening?EType.MarubozuWeakening:
                     EType.Marubozu);
            }

            // No particular type
            return(EType.Unknown);
        }
Пример #3
0
 public CandlePattern(ECandlePattern pattern, TradeType tt, RangeF range, Idx index, QuoteCurrency ep)
 {
     Pattern = pattern;
     TT      = tt;
     Range   = range;
     Index   = index;
     EP      = ep;
 }
Пример #4
0
        public PriceTick(double calgo_index, long timestamp, QuoteCurrency ask, QuoteCurrency bid)
        {
            if (ask < bid)
            {
                throw new Exception("Negative spread");
            }

            Index     = calgo_index;
            Timestamp = timestamp;
            Ask       = ask;
            Bid       = bid;
        }
Пример #5
0
        /// <summary>Return the value (in quote currency) of this order when the price is at 'price' (not scaled by volume)
        /// Positive values mean in profit. Negative values mean loss</summary>
        public QuoteCurrency ValueAt(QuoteCurrency price, bool consider_sl, bool consider_tp)
        {
            var sign = TradeType.Sign();

            // If 'price' is beyond the stop loss, clamp at the stop loss value
            if (consider_sl && SL != null && Maths.Sign(SL.Value - price) == sign)
            {
                price = SL.Value;
            }

            // If 'price' is beyond the take profit, clamp at the take profit value
            if (consider_tp && TP != null && Maths.Sign(price - TP.Value) == sign)
            {
                price = TP.Value;
            }

            // Return the position value in quote currency
            return(sign * (price - EP));
        }
Пример #6
0
        /// <summary>Return the maximum volume to trade given a relative stop loss value</summary>
        public long ChooseVolume(Instrument instr, QuoteCurrency sl_rel, double?risk = null)
        {
            // Find the amount we're allowed to risk
            // Scale down a little bit to prevent issues comparing the returned SL to BalanceToRisk
            var balance_to_risk = BalanceToRisk * 0.99;

            if (balance_to_risk == 0)
            {
                return(0);
            }

            // Set a hard lower limit on 'SL'
            if (sl_rel < 5.0 * instr.PipSize)
            {
                sl_rel = 5.0 * instr.PipSize;
            }

            // Get this amount in quote currency
            var volume = (risk ?? 1.0) * balance_to_risk / instr.Symbol.QuoteToAcct(sl_rel);

            return(instr.Symbol.NormalizeVolume(volume, RoundingMode.Down));
        }
Пример #7
0
        /// <summary>Create a trade with explicit values</summary>
        public Trade(Instrument instr, TradeType tt, string label, QuoteCurrency ep, QuoteCurrency?sl, QuoteCurrency?tp, long volume, string comment = null, Idx?idx = null, EResult result = EResult.Unknown)
        {
            CAlgoId    = null;
            TradeIndex = m_trade_index++;
            TradeType  = tt;
            Instrument = instr;
            Result     = result;
            EntryIndex = (double)(idx ?? instr.IdxNow) - instr.IdxFirst;
            ExitIndex  = EntryIndex;
            Expiration = null;
            Label      = label ?? string.Empty;
            Comment    = comment ?? string.Empty;

            EP     = ep;
            SL     = sl;
            TP     = tp;
            Volume = volume;

            MaxFavourableExcursion = 0.0;
            MaxAdverseExcursion    = 0.0;
            NetProfit   = 0.0;
            GrossProfit = 0.0;
        }
Пример #8
0
 /// <summary>Convert a price in quote currency to pips</summary>
 public static Pips QuoteToPips(this Symbol sym, QuoteCurrency price)
 {
     return((double)price / sym.PipSize);
 }
Пример #9
0
        /// <summary>Returns the price peaks using a window with size 'window_size'</summary>
        public IEnumerable <Peak> FindPeaks(Idx iend)
        {
            // Create window buffers for the high/low prices
            var price_hi = new QuoteCurrency[WindowSize];
            var price_lo = new QuoteCurrency[WindowSize];

            for (int i = 0; i != WindowSize; ++i)
            {
                price_hi[i] = -double.MaxValue;
                price_lo[i] = +double.MaxValue;
            }

            // Look for peaks
            int d = 0, hh = -1, ll = -1, hcount = 0, lcount = 0;

            for (Idx i = iend; i-- != Instrument.IdxFirst; d = (d + 1) % WindowSize)
            {
                var candle = Instrument[i];
                Beg = i;

                // Add the new price values
                price_hi[d] = candle.High;
                price_lo[d] = candle.Low;

                // Find the ring buffer index of the highest and lowest price
                var h = price_hi.IndexOfMaxBy(x => x);
                var l = price_lo.IndexOfMinBy(x => x);

                // If the high is the highest for the full window size, output it
                if (hh == h)
                {
                    if (++hcount == WindowSize)
                    {
                        // Skip index == 0 because it's not a complete candle
                        var idx = i + (d - hh + WindowSize) % WindowSize;
                        if (Instrument.IdxLast - idx > 1)
                        {
                            yield return(new Peak(idx, price_hi[hh], true));
                        }
                        hh     = -1;
                        hcount = 0;
                    }
                }
                else
                {
                    hh     = h;
                    hcount = 1;
                }

                // If the low is the lowest for the full window size, output it
                if (ll == l)
                {
                    if (++lcount == WindowSize)
                    {
                        // Skip index == 0 because it's not a complete candle
                        var idx = i + (d - ll + WindowSize) % WindowSize;
                        if (Instrument.IdxLast - idx > 1)
                        {
                            yield return(new Peak(idx, price_lo[ll], false));
                        }
                        ll     = -1;
                        lcount = 0;
                    }
                }
                else
                {
                    ll     = l;
                    lcount = 1;
                }
            }
        }
Пример #10
0
 public Level(QuoteCurrency price)
 {
     Price    = price;
     Strength = 0;
     Average  = new Avr();
 }
Пример #11
0
 public StationaryPoint(Idx index, QuoteCurrency price, int sign)
 {
     Index = index;
     Price = price;
     Sign  = sign;
 }
Пример #12
0
 public Peak(Idx index, QuoteCurrency price, bool high)
 {
     Index = index;
     Price = price;
     High  = high;
 }
Пример #13
0
 /// <summary>Return the value (in quote currency) of this position when the price is at 'price'</summary>
 public static QuoteCurrency ValueAt(this PendingOrder pos, QuoteCurrency price, bool consider_sl, bool consider_tp)
 {
     return(new Order(pos).ValueAt(price, consider_sl, consider_tp));
 }
Пример #14
0
 /// <summary>True if there are open positions within a range of 'price'</summary>
 public bool NearbyPositions(string label, QuoteCurrency price, double min_trade_dist, int sign = 0)
 {
     return(sign == 0
                         ? Positions.Any(x => Math.Abs(x.EntryPrice - price) < min_trade_dist)
                         : Positions.Any(x => Math.Abs(x.EntryPrice - price) < min_trade_dist && x.Sign() == sign));
 }
Пример #15
0
        /// <summary>Set the SL or TP for a position such that it will close when the price hits 'price'</summary>
        public void CloseAt(Instrument instr, Position position, QuoteCurrency price)
        {
            Debug.Assert(instr.SymbolCode == position.SymbolCode);
            Bot.TradeStats.Event(position, "CloseAt");

            var trade = (Trade)null;

            if (position.TradeType == TradeType.Buy)
            {
                // If the current price is not between 'price' and 'position.StopLoss' move the SL to 'price'
                if (!instr.CurrentPrice(-1).Within(position.StopLoss ?? -double.MaxValue, price))
                {
                    trade = new Trade(instr, position)
                    {
                        SL = price - instr.Spread
                    }
                }
                ;

                // If the current price is not between 'price' and 'position.TakeProfit' move the TP to 'price'
                else if (!instr.CurrentPrice(+1).Within(price, position.TakeProfit ?? +double.MaxValue))
                {
                    trade = new Trade(instr, position)
                    {
                        TP = price
                    }
                }
                ;

                // If the current price spans 'price' close immediately
                else
                {
                    trade = null;
                }
            }
            else
            {
                // If the current price is not between 'price' and 'position.StopLoss' move the SL to 'price'
                if (!instr.CurrentPrice(+1).Within(price, position.StopLoss ?? +double.MaxValue))
                {
                    trade = new Trade(instr, position)
                    {
                        SL = price + instr.Spread
                    }
                }
                ;

                // If the current price is not between 'price' and 'position.TakeProfit' move the TP to 'price'
                else if (!instr.CurrentPrice(-1).Within(position.TakeProfit ?? -double.MaxValue, price))
                {
                    trade = new Trade(instr, position)
                    {
                        TP = price
                    }
                }
                ;

                // If the current price spans 'price' close immediately
                else
                {
                    trade = null;
                }
            }

            // Update or close the trade
            if (trade != null)
            {
                // Move the SL or TP
                ModifyOrder(position, trade);
            }
            else
            {
                // Close immediately if the price spread spans 'price'
                ClosePosition(position, "CloseAt at current Price");
            }
        }
Пример #16
0
 /// <summary>Convert a price in quote currency to account currency. Remember to multiple by trade volume</summary>
 public static AcctCurrency QuoteToAcct(this Symbol sym, QuoteCurrency price)
 {
     return((double)(sym.QuoteToPips(price) * sym.PipValue));
 }
Пример #17
0
 /// <summary>Return the value (in quote currency) of this position when the price is at 'price'</summary>
 public static QuoteCurrency ValueAt(this ITrade pos, QuoteCurrency price, bool consider_sl, bool consider_tp)
 {
     return(new Order(pos, true).ValueAt(price, consider_sl, consider_tp));
 }
Пример #18
0
 /// <summary>
 /// 'rel_price' is the price in the profit direction that trips the break even. e.g. MCS would trip break even when the price is in profit by MCS.
 /// 'bias' is the offset from break even</summary>
 public PositionManagerMoveToBreakEven(Rylobot bot, Position position, QuoteCurrency rel_price, QuoteCurrency?bias = null)
     : base(bot, position)
 {
     m_rel_price = rel_price;
     m_bias      = bias;
 }
Пример #19
0
 public TargetEntryData(QuoteCurrency price, TradeType tt)
 {
     Price = price;
     TT    = tt;
 }