示例#1
0
        /// <summary>
        /// Create a trade with automatic SL and TP levels set.
        /// SL/TP levels are set based on the current account balance (even if 'idx' != 0)</summary>
        /// <param name="instr">The instrument to be traded</param>
        /// <param name="tt">Whether to buy or sell</param>
        /// <param name="label">Optional. An identifying name for the trade</param>
        /// <param name="ep">Optional. The price at which the trade was entered. (default is current ask/bid price)</param>
        /// <param name="sl">Optional. The stop loss (absolute) to use instead of automatically finding one</param>
        /// <param name="tp">Optional. The take profit (absolute) to use instead of automatically finding one</param>
        /// <param name="risk">Optional. Scaling factor for the amount to risk. (default is 1.0)</param>
        /// <param name="comment">Optional. A comment/tag associated with the trade</param>
        /// <param name="idx">Optional. The instrument index of when the trade was created. (default is the current time)</param>
        public Trade(Instrument instr, TradeType tt, string label = null, QuoteCurrency?ep = null, QuoteCurrency?sl = null, QuoteCurrency?tp = null, double?risk = null, string comment = null, Idx?idx = null, EResult result = EResult.Unknown)
            : this(instr, tt, label, 0, null, null, 0, comment : comment, idx : idx, result : result)
        {
            try
            {
                var bot   = instr.Bot;
                var sign  = tt.Sign();
                Idx index = idx ?? 0;
                bot.Debugging.Trace("Creating Trade (Index = {0})".Fmt(TradeIndex));

                // If the index == 0, add the fractional index amount
                if (index == 0)
                {
                    var ticks_elapsed    = bot.UtcNow.Ticks - instr.Latest.Timestamp;
                    var ticks_per_candle = instr.TimeFrame.ToTicks();
                    EntryIndex += Maths.Clamp((double)ticks_elapsed / ticks_per_candle, 0.0, 1.0);
                    ExitIndex   = EntryIndex;
                }

                // Set the trade entry price
                EP = ep ?? (index == 0
                                        ? (QuoteCurrency)instr.CurrentPrice(sign)                                   // Use the latest price
                                        : (QuoteCurrency)instr[index].Open + (sign > 0 ? instr.Symbol.Spread : 0)); // Use the open price of the candle at 'index'

                // Choose a risk scaler
                risk = risk ?? 1.0;

                // Find the account currency value of the available risk
                var balance_to_risk = bot.Broker.BalanceToRisk * risk.Value;
                if (balance_to_risk == 0)
                {
                    throw new Exception("Insufficient available risk. Current Risk: {0}%, Maximum Risk: {1}%".Fmt(100 * bot.Broker.TotalRiskFrac, 100.0 * bot.Settings.MaxRiskFrac));
                }

                // Require the SL to be at least 2 * the median candle size
                var volatility = instr.Symbol.QuoteToAcct(2 * instr.MCS * instr.Symbol.VolumeMin);
                if (balance_to_risk < volatility)
                {
                    throw new Exception("Insufficient available risk. Volatility: {0}, Balance To Risk: {1}".Fmt(volatility, balance_to_risk));
                }

                // Get the instrument to recommend trade exit conditions
                var exit = instr.ChooseTradeExit(tt, EP, idx: index, risk: risk);
                TP     = tp != null ? tp.Value : exit.TP;
                SL     = sl != null ? sl.Value : exit.SL;
                Volume = sl != null?instr.Bot.Broker.ChooseVolume(instr, sl.Value / risk.Value) : exit.Volume;
            }
            catch (Exception ex)
            {
                Error = ex;
            }
        }