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); }
/// <summary>Watch for bot stopped</summary> protected override void OnBotStopping() { base.OnBotStopping(); // Log the whole instrument Debugging.Dump(Instrument); }
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; }
/// <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); } }
/// <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)); }); }
/// <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)); } }); }
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); }
/// <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; }
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)"); } }
/// <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; } }
/// <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)); }
/// <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; } } }
/// <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(); } }
/// <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)); }
/// <summary>Debugging output</summary> public override void Dump() { Debugging.CurrentPrice(Instrument); Debugging.Dump(Instrument); }
/// <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; } } } }
/// <summary>Debugging output</summary> public override void Dump() { Debugging.CurrentPrice(Instrument); Debugging.Dump(Instrument, range: new Range(-100, 1), high_res: 20.0); }
/// <summary></summary> public override void Dump() { Debugging.CurrentPrice(Instrument); Debugging.Dump(Instrument, range: new RangeF(-100, 1), mas: new[] { EMA0, EMA1 }); }
public override void Dump() { Debugging.CurrentPrice(Instrument); Debugging.Dump(Instrument, range: new Range(-100, 1), indicators: new[] { MA0, MA1 }); }
/// <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 }); }
/// <summary>Debugging output</summary> public override void Dump() { Debugging.CurrentPrice(Instrument); Debugging.Dump(Instrument, indicators: new[] { MA0, MA1, MA2 }); }
/// <summary>Debugging output</summary> public override void Dump() { Debugging.CurrentPrice(Instrument); Debugging.Dump(Instrument, indicators: new[] { Donchian }); }
/// <summary></summary> protected override void OnBotStopping() { base.OnBotStopping(); Debugging.Dump(Instrument); }