예제 #1
0
        private static void PerformanceTesting(string fen, int perftDepth, TimeSpan timespan)
        {
            var position = BoardParsing.PositionFromFen(fen);

            Debugging.Dump(position);

            var       moveGen          = new MoveGenerator();
            var       perft            = new Perft(moveGen);
            Stopwatch overallStopwatch = new Stopwatch();

            overallStopwatch.Start();
            while (true)
            {
                int perftNum = perftDepth;
                Console.Write($"Perft {perftNum}: ");

                Stopwatch sw = new Stopwatch();
                sw.Start();
                int perftResults = perft.GoPerft(position, perftNum);
                sw.Stop();
                double knps = ((double)perftResults) / sw.ElapsedMilliseconds;  // it just works out
                Console.WriteLine($"{perftResults} ({knps:F2} knps)");
                if (overallStopwatch.Elapsed > timespan)
                {
                    break;
                }
            }

            //perft.GoPerft(position, perftDepth);
        }
예제 #2
0
        /// <summary>Watch for bot stopped</summary>
        protected override void OnBotStopping()
        {
            base.OnBotStopping();

            // Log the whole instrument
            Debugging.Dump(Instrument);
        }
예제 #3
0
 public MagicMoveTable Build()
 {
     Debug.Assert(_infos.Count == 64);
     if (_magicFailed)
     {
         Debugging.Dump("***** Invalid magic provided to magic move table builder; need to recalc magic tables.");
     }
     return(new MagicMoveTable(_infos.Values.ToArray()));
 }
        /// <summary></summary>
        protected override void StepCore()
        {
            // If the SL is on the winning side, let the trade run its course
            var sl_rel = Position.StopLossRel();

            if (sl_rel < 0)
            {
                return;
            }

            var mcs             = Instrument.MCS;
            var sign            = Position.Sign();
            var price           = Instrument.LatestPrice;
            var trend_sign_slow = Strategy.TrendSignSlow;
            var trend_sign_fast = Strategy.TrendSignFast;

            // If the position opposes the slow trend, try to close it at break even
            if (sign == -trend_sign_slow && sign == -trend_sign_fast)
            {
                var cp = price.Price(-sign);

                // Choose a SL based on SnR levels
                var snr  = new SnR(Instrument); Debugging.Dump(snr);
                var near = snr.Nearest(cp, -sign, min_dist: mcs * 0.5);
                var sl   = near != null ? near.Price : cp - sign * mcs;
                if (Math.Abs(sl - Position.EntryPrice) < sl_rel)
                {
                    Broker.ModifyOrder(Instrument, Position, sl: sl);
                    Debugging.Trace("  +Position opposes the trend (trend={0}), closing at break even".Fmt(trend_sign_slow));
                    return;
                }
            }

            // If the trade is better than RtR=1:1, and the close probability is high close the trade
            // For closing positions, use Ask when the price is high, Bit when the price is low
            var prob_sign = Strategy.ProbSign;
            var prob      = Strategy.Prob(prob_sign);

            if (sign == prob_sign && Math.Abs(prob) > StrategyPriceDistribution.ClosePositionProb)
            {
                // If the price gradient is in the direction of the trade, don't close it
                var d = Instrument.HighRes.FirstDerivative(-1);
                if (Math.Sign(d) == sign)
                {
                    return;
                }

                var min_profit = Instrument.Symbol.QuoteToAcct(sl_rel * Position.Volume);
                if (Position.NetProfit > min_profit)
                {
                    Debugging.Trace("  +Close Prob: {0}".Fmt(prob));
                    Broker.ClosePosition(Position);
                }
            }
        }
        /// <summary>Watch for bot stopped</summary>
        protected override void OnBotStopping()
        {
            base.OnBotStopping();

            // Log the whole instrument
            Debugging.DebuggingEnabled = true;
            Debugging.ReportEdge(100);
            Debugging.Dump(Debugging.AllTrades.Values);
            Debugging.Dump(Instrument, mas: new[] { MA0, MA1 });
            Debugging.DebuggingEnabled = false;
        }
예제 #6
0
 /// <summary>Debugging Output</summary>
 private void Dump()
 {
     if (!Debugger.IsAttached)
     {
         return;
     }
     Debugging.Dump(Instrument, range_: new Range(-100, 1), high_res: 0, emas: new[] { 200, 55 });
     Debugging.Dump(new SnR(Instrument, -100, 0));
     if (Position != null)
     {
         Debugging.LogTrade(Position);
     }
 }
예제 #7
0
 /// <summary>Debugging, output current state</summary>
 public override void Dump()
 {
     Debugging.CurrentPrice(Instrument);
     Debugging.Dump(Instrument, range: new Range(-100, 1));
     Debugging.Dump("channel.ldr", ldr =>
     {
         if (Channel == null)
         {
             return;
         }
         var ch = Channel.Value;
         ldr.Rect("channel", 0xFF0000FF, AxisId.PosZ, ch.Idx.Sizef, ch.Price.Sizef, false,
                  new v4(ch.Idx.Midf, ch.Price.Midf, 0f, 1f));
     });
 }
예제 #8
0
        /// <summary>Watch for bot stopped</summary>
        protected override void OnBotStopping()
        {
            base.OnBotStopping();

            // Log the whole instrument
            Debugging.DebuggingEnabled = true;
            Debugging.ReportEdge(100);
            Debugging.Dump(Debugging.AllTrades.Values);
            Debugging.Dump(Instrument, mas: new[] { Indicator.EMA(Instrument, 5), Indicator.EMA(Instrument, 15), Indicator.EMA(Instrument, 100) });
            Debugging.Dump("channels.ldr", ldr =>
            {
                foreach (var ch in Channels)
                {
                    ldr.Rect("channel", 0xFF0000FF, AxisId.PosZ, ch.Idx.Sizef, ch.Price.Sizef, false,
                             new v4(ch.Idx.Midf, ch.Price.Midf, 0f, 1f));
                }
            });
        }
예제 #9
0
        private static void DivideTesting(string fen, int depth, params string[] moves)
        {
            var position = BoardParsing.PositionFromFen(fen);

            Debugging.Dump(position);

            var moveGen = new MoveGenerator();
            var perft   = new Perft(moveGen);

            foreach (var moveStr in moves)
            {
                Move move = BoardParsing.GetMoveFromCoordinateString(moveGen, position, moveStr);
                position = Position.MakeMove(new Position(), move, position);
                Debugging.Dump(position);
            }

            GoDivide(moveGen, perft, position, depth - moves.Length);
        }
예제 #10
0
        /// <summary>Watch for bot stopped</summary>
        protected override void OnBotStopping()
        {
            base.OnBotStopping();

            // Log the whole instrument
            Debugging.DebuggingEnabled = true;
            Debugging.ReportEdge(100);

            var ldr = new pr.ldr.LdrBuilder();

            foreach (var trade in Debugging.AllTrades.Values)
            {
                Debugging.Dump(trade, ldr_: ldr);
                Debugging.Dump(new PricePeaks(Instrument, trade.EntryIndex + Instrument.IdxFirst), ldr_: ldr);
            }
            ldr.ToFile(Debugging.FP("trades.ldr"));

            Debugging.Dump(Instrument);
            Debugging.DebuggingEnabled = false;
        }
예제 #11
0
        private static void IncrementalPerft(string fen, int maxDepth)
        {
            var position = BoardParsing.PositionFromFen(fen);

            Debugging.Dump(position);

            var moveGen = new MoveGenerator();
            var perft   = new Perft(moveGen);

            for (int i = 1; i <= maxDepth; i++)
            {
                Console.Write($"Perft {i}: ");

                Stopwatch sw = new Stopwatch();
                sw.Start();
                int perftResults = perft.GoPerft(position, i);
                sw.Stop();
                double knps = ((double)perftResults) / sw.ElapsedMilliseconds;  // it just works out
                Console.WriteLine($"{perftResults} ({knps:F2} knps)");
            }
        }
예제 #12
0
        /// <summary></summary>
        public override void Step()
        {
            // Avoid boundary cases in the data
            if (Instrument.Count < PredictorNeuralNet.HistoryWindow + WindowSize)
            {
                return;
            }

            // Only do this per candle
            if (!Instrument.NewCandle)
            {
                return;
            }

            // At a candle close:
            //  Record as many indicator features as I can think of
            //  Imagine a trade of both directions was created at the open on this new candle
            //  See how the trades plays out over the next WindowSize candles
            //  Output 'buy' 'sell' or 'no trade' based on the trade result
            // This means the training data will contain the state of all indicators at this
            // candle close, and the ideal trade to have taken at that point.

            // Use a position in the past as the 'current' position so that we can
            // use the future candle data to see what actually happens.
            // 'index - 1' is the candle that just closed, 'index' is the new candle
            var    index   = Instrument.Count - WindowSize;
            NegIdx neg_idx = Instrument.FirstIdx + index;

            // Get features up to the last closed candle, since we don't know anything about 'index' yet
            var features = NNet.Features;

            // Create a buy and sell trade at the open of the new candle
            // Use the Broker's ChooseSL/TP so that the trades are realistic
            var entry = Instrument[neg_idx];
            var buy   = new Trade(Bot, Instrument, TradeType.Buy, neg_idx: neg_idx);
            var sel   = new Trade(Bot, Instrument, TradeType.Sell, neg_idx: neg_idx);

            // See how each trade plays out over the next WindowSize candles
            for (var i = neg_idx; i != Instrument.LastIdx; ++i)
            {
                var c = Instrument[i];
                buy.AddCandle(c, i);
                sel.AddCandle(c, i);
            }

            // Select the best trade as the desired output for the given features
            var is_buy = buy.PeakRtR > sel.PeakRtR && buy.Result != Trade.EResult.Open;
            var is_sel = sel.PeakRtR > buy.PeakRtR && sel.Result != Trade.EResult.Open;
            var labels = "|labels {0} {1} {2} ".Fmt(is_buy?1:0, is_sel?1:0, !(is_buy || is_sel)?1:0);

            // Select the file to write to
            var fs = (index % TrainToTestRatio) == 0 ? m_testing : m_training;

            // Output the labels
            fs.Write(labels);

            // Write the feature string (last so the training data is easier to read)
            fs.Write(features);

            // New line
            fs.WriteLine();

            // Write the results to a file
            if (cooldown == 0)
            {
                if (m_ldr == null)
                {
                    m_ldr = new pr.ldr.LdrBuilder();
                    m_grp = m_ldr.Group("Training");
                }
                if (buy.PeakRtR > sel.PeakRtR)
                {
                    Debugging.Dump(buy, ldr_: m_ldr);
                }
                else
                {
                    Debugging.Dump(sel, ldr_: m_ldr);
                }

                cooldown = 20;
            }
            else
            {
                --cooldown;
            }
        }
예제 #13
0
 /// <summary>Debugging, output current state</summary>
 public override void Dump()
 {
     Debugging.CurrentPrice(Instrument);
     Debugging.Dump(Instrument, range: new Range(-100, 1));
     Debugging.Dump(new SnR(Instrument, tf: TimeFrame.Hour8));
 }
예제 #14
0
        /// <summary>Called when new data is received</summary>
        public override void Step()
        {
            base.Step();
            using (Broker.SuspendRiskCheck(ignore_risk: true))
            {
                const double TakeProfitFrac = 1.020;
                const double ReverseFrac    = 0.998;
                Dump();

                // The unit of volume to trade
                var mcs = Instrument.MCS;
                var ep  = Instrument.LatestPrice.Mid;
                var vol = Broker.ChooseVolume(Instrument, 5.0 * mcs);

                // Open a trade in the direction of the trend
                if (ProfitSign == 0)
                {
                    Dump();
                    Debugging.Trace("Idx={0},Tick={1} - Setting profit sign ({2}) - Equity = ${3}".Fmt(Instrument.Count, Bot.TickNumber, TrendSign, Equity));

                    var tt    = CAlgo.SignToTradeType(TrendSign);
                    var trade = new Trade(Instrument, tt, Label, ep, null, null, vol);
                    Broker.CreateOrder(trade);
                    LastEquity = Equity;
                }

                // While the profit direction is the same as the trend direction
                // look for good spots to add hedged pending orders
                if (ProfitSign == TrendSign)
                {
                    // If the current price is at a SnR level, add pending orders on either side.
                    // Hopefully price will reverse at the SnR level and only trigger one of the pending orders.
                    // If price then reverses we can sell an existing profitable trade and be left with the
                    // profit direction going in the right direction
                    var snr       = new SnR(Instrument, ep);
                    var lvl_above = snr.Nearest(ep, +1, min_dist: 0.5 * mcs, min_strength: 0.7);
                    var lvl_below = snr.Nearest(ep, -1, min_dist: 0.5 * mcs, min_strength: 0.7);

                    // Choose price levels for the pending orders
                    var above = lvl_above != null ? lvl_above.Price + 0.5 * mcs : ep + mcs;
                    var below = lvl_below != null ? lvl_below.Price - 0.5 * mcs : ep - mcs;

                    // Only recreate if necessary
                    if (!PendingOrders.Any(x => x.TradeType == TradeType.Buy && Maths.FEql(x.TargetPrice, above, 5 * Instrument.PipSize)) ||
                        !PendingOrders.Any(x => x.TradeType == TradeType.Sell && Maths.FEql(x.TargetPrice, below, 5 * Instrument.PipSize)))
                    {
                        Dump();
                        Debugging.Dump(snr);
                        Debugging.Trace("Idx={0},Tick={1} - Adjusting pending orders - Equity = ${2}".Fmt(Instrument.Count, Bot.TickNumber, Equity));

                        // Cancel any other pending orders further away than these too
                        Broker.CancelAllPendingOrders(Label);

                        var buy = new Trade(Instrument, TradeType.Buy, Label, above, null, null, vol);
                        var sel = new Trade(Instrument, TradeType.Sell, Label, below, null, null, vol);
                        Broker.CreatePendingOrder(buy);
                        Broker.CreatePendingOrder(sel);
                    }
                }

                // If the profit is against the Trend, do nothing until losing a fraction of last equity
                if (ProfitSign != TrendSign && Equity < ReverseFrac * LastEquity)
                {
                    Dump();
                    Debugging.Trace("Idx={0},Tick={1} - Changing profit sign to ({2}) - Equity = ${3}".Fmt(Instrument.Count, Bot.TickNumber, TrendSign, Equity));
                    var sign = -ProfitSign;

                    // Try to reverse the sign by closing profitable positions
                    foreach (var pos in Positions.Where(x => x.Sign() != sign && x.NetProfit > 0).OrderBy(x => - x.NetProfit).ToArray())
                    {
                        Broker.ClosePosition(pos);

                        // Break out when the profit direction has been reversed
                        if (ProfitSign == sign)
                        {
                            break;
                        }
                    }

                    // Couldn't reverse the sign by closing positions, open a new one
                    if (ProfitSign != sign)
                    {
                        var tt          = CAlgo.SignToTradeType(sign);
                        var reverse_vol = Math.Abs(NetVolume) + vol;
                        var trade       = new Trade(Instrument, tt, Label, ep, null, null, reverse_vol);
                        Broker.CreateOrder(trade);
                    }
                    LastEquity = Equity;
                }

                // If equity is greater than a threshold, take profits
                if (Equity > TakeProfitFrac * LastEquity)
                {
                    Dump();
                    Debugging.Trace("Idx={0},Tick={1} - Profit taking - Equity = ${2}".Fmt(Instrument.Count, Bot.TickNumber, Equity));

                    var sign = ProfitSign;
                    foreach (var pos in Positions.Where(x => x.Sign() == sign && x.NetProfit > 0).OrderBy(x => - x.NetProfit).ToArray())
                    {
                        if (pos.Volume >= Math.Abs(NetVolume))
                        {
                            continue;
                        }
                        Broker.ClosePosition(pos);
                    }
                    LastEquity = Equity;
                }
            }
        }
예제 #15
0
        /// <summary>Called when new data is received</summary>
        public override void Step()
        {
            // Only on new candles
            Position = FindLivePosition(Position);
            if (!Instrument.NewCandle)
            {
                return;
            }

            if (Debugger.IsAttached)
            {
                Debugging.Dump(Instrument, high_res: 20.0, emas: new[] { 100 });
                if (Instrument.Count == 230)
                {
                    Debug.WriteLine("Break");
                }
            }

            var sym = Instrument.Symbol;
            var mcs = Instrument.MedianCandleSize(-10, 0);
            var C0  = Instrument[0];
            var C1  = Instrument[-1];
            var C2  = Instrument[-2];

            // One at a time
            if (Position == null)
            {
                TradeType tt;
                string    msg;

                // Look for a reversal
                int           reversal_direction;
                QuoteCurrency target_entry;
                if (!Instrument.IsCandlePattern(0, out reversal_direction, out target_entry))
                {
                    return;
                }

                var preceeding_trend = Instrument.MeasureTrend(-10, 0);

                var tt_confirmation = C1.Bullish ? TradeType.Buy : TradeType.Sell;

                const double EmaSlopeToMCS = 20;
                var          ema           = Bot.Indicators.ExponentialMovingAverage(Bot.MarketSeries.Close, 100);
                var          ema_slope     = ema.Result.FirstDerivative(ema.Result.Count - 1) * EmaSlopeToMCS / mcs;

                // If the EMA slope is flat, look for ranging
                if (Math.Abs(ema_slope) < 1.0)
                {
                    // Side of the EMA. Must be significantly to one side of the EMA
                    var dist = C1.Close - ema.Result.LastValue;
                    if (Math.Abs(dist) < mcs)
                    {
                        return;
                    }

                    tt  = C1.Close < ema.Result.LastValue ? TradeType.Buy : TradeType.Sell;
                    msg = "{0} - ranging EMA. Slope = {1}, Distance = {2}".Fmt(tt, ema_slope, dist);
                }
                // Otherwise look for indecision near the EMA
                else
                {
                    var dist = C1.Close - ema.Result.LastValue;
                    if (Maths.Abs(dist) > mcs)
                    {
                        return;
                    }

                    tt  = ema_slope > 0.0 ? TradeType.Buy : TradeType.Sell;
                    msg = "{0} - trending EMA. Slope = {1}, Dist = {2}".Fmt(tt, ema_slope, dist);
                }

                // Check the candle confirms the direction
                if (tt != tt_confirmation)
                {
                    return;
                }

                var sign  = tt.Sign();
                var rtr   = new RangeF(1.0, 2.0);
                var trade = new Trade(Bot, Instrument, tt, Label, rtr_range: rtr);
                Bot.Print(msg);
                Position        = Bot.Broker.CreateOrder(trade);
                PositionManager = new PositionManager(Instrument, Position);
            }
            else
            {
                PositionManager.Step();
            }
        }
예제 #16
0
 /// <summary>Output the current state</summary>
 public override void Dump()
 {
     Debugging.Dump(Instrument, range: new Range(-100, 1), high_res: 20.0);
     //Debugging.Dump(EMA0.Extrapolate().Curve, "ema0", Colour32.Green, new RangeF(-5.0, 5.0));
 }
예제 #17
0
 /// <summary>Debugging output</summary>
 public override void Dump()
 {
     Debugging.CurrentPrice(Instrument);
     Debugging.Dump(Instrument);
 }
예제 #18
0
        /// <summary>Called when new data is received</summary>
        public override void Step()
        {
            base.Step();
            if (Instrument.NewCandle)
            {
                Dump();
            }

            // Don't open new positions while there are pending orders or existing positions
            if (Positions.Any() || PendingOrders.Any())
            {
                return;
            }

            // Look for peak patterns
            TradeType     tt;
            QuoteCurrency ep;
            var           pat = Instrument.IsPeakPattern(Instrument.IdxNow, out tt, out ep);

            if (pat != null)
            {
                var pattern = pat.Value;

                Dump();
                Debugging.Dump(new PricePeaks(Instrument, 0));
                Debugging.Dump(new SnR(Instrument));
                Debugging.Trace("Peak pattern: {0}".Fmt(pattern));

                var sign = tt.Sign();
                var mcs  = Instrument.MCS;

                // Convert the patterns to trades
                switch (pattern)
                {
                case EPeakPattern.BreakOutHigh:
                case EPeakPattern.BreakOutLow:
                {
                    // For break outs, enter immediately and use a candle
                    // follow position manager because they tend to run.
                    var price_range = Instrument.PriceRange(-10, 1);
                    var sl          = price_range.Mid - sign * price_range.Size * 0.6;
                    var tp          = (QuoteCurrency?)null;
                    var vol         = Broker.ChooseVolume(Instrument, Math.Abs(ep - sl), risk: Risk);
                    var trade       = new Trade(Instrument, tt, Label, ep, sl, tp, vol);
                    var pos         = Broker.CreateOrder(trade);
                    if (pos != null)
                    {
                        PositionManagers.Add(new PositionManagerCandleFollow(this, pos, 5));
                    }

                    break;
                }

                case EPeakPattern.HighReversal:
                case EPeakPattern.LowReversal:
                {
                    // For reversals, enter when the price is near the trend line.
                    // Use a fixed SL/TP
                    var price_range = Instrument.PriceRange(-10, 1);
                    var sl          = price_range.Mid - sign * price_range.Size * 0.6;
                    var tp          = price_range.Mid + sign * price_range.Size * 0.4;
                    var vol         = Broker.ChooseVolume(Instrument, Math.Abs(ep - sl), risk: Risk);

                    // If the current price is better than the entry price, enter immediately
                    if (sign * (ep - Instrument.CurrentPrice(sign)) > 0)
                    {
                        var trade = new Trade(Instrument, tt, Label, ep, sl, tp, vol);
                        Broker.CreateOrder(trade);
                    }
                    else
                    {
                        var order = new Trade(Instrument, tt, Label, ep, sl, tp, vol)
                        {
                            Expiration = Instrument.ExpirationTime(1)
                        };
                        Broker.CreatePendingOrder(order);
                    }
                    break;
                }
                }
            }
        }
예제 #19
0
 /// <summary>Debugging output</summary>
 public override void Dump()
 {
     Debugging.CurrentPrice(Instrument);
     Debugging.Dump(Instrument, range: new Range(-100, 1), high_res: 20.0);
 }
예제 #20
0
 /// <summary></summary>
 public override void Dump()
 {
     Debugging.CurrentPrice(Instrument);
     Debugging.Dump(Instrument, range: new RangeF(-100, 1), mas: new[] { EMA0, EMA1 });
 }
예제 #21
0
 public override void Dump()
 {
     Debugging.CurrentPrice(Instrument);
     Debugging.Dump(Instrument, range: new Range(-100, 1), indicators: new[] { MA0, MA1 });
 }
예제 #22
0
 /// <summary>Debugging output</summary>
 public override void Dump()
 {
     Debugging.CurrentPrice(Instrument);
     Debugging.Dump(Instrument, range: new Range(-100, 1));
     Debugging.Dump(MACD, range: new Range(-100, 1));
 }
 /// <summary>Debugging output</summary>
 public override void Dump()
 {
     Debugging.CurrentPrice(Instrument);
     Debugging.Dump(Instrument, range: new Range(-100, 1), mas: new[] { MA0, MA1 }, high_res: 20.0);
     Debugging.Dump(PriceDistribution, +5, prob: new[] { 0.1, 0.5, 0.9 });
 }
예제 #24
0
 /// <summary>Debugging output</summary>
 public override void Dump()
 {
     Debugging.CurrentPrice(Instrument);
     Debugging.Dump(Instrument, indicators: new[] { MA0, MA1, MA2 });
 }
예제 #25
0
 /// <summary>Debugging output</summary>
 public override void Dump()
 {
     Debugging.CurrentPrice(Instrument);
     Debugging.Dump(Instrument, indicators: new[] { Donchian });
 }
예제 #26
0
 /// <summary></summary>
 protected override void OnBotStopping()
 {
     base.OnBotStopping();
     Debugging.Dump(Instrument);
 }