コード例 #1
0
ファイル: Trade.cs プロジェクト: Andrew-Biggins/GapTrader
        public Trade(ISavedTrade savedTrade)
        {
            StrategyEntryLevel = savedTrade.StrategyEntryLevel;
            StopLevel          = savedTrade.StopLevel;
            Target             = savedTrade.Target;
            OpenLevel          = savedTrade.OpenLevel;

            Direction = Target > StopLevel
                ? TradeDirection.Long
                : TradeDirection.Short;

            CloseLevel = savedTrade.CloseLevel == -1
                ? Option.None <double>()
                : Option.Some(savedTrade.CloseLevel);

            OpenTime = savedTrade.OpenTime;

            CloseTime = savedTrade.CloseTime == DateTime.MinValue
                ? Option.None <DateTime>()
                : Option.Some(savedTrade.CloseTime);

            Size = savedTrade.Size;

            MaximumAdverseExcursionPoints = savedTrade.MaximumAdverseExcursion == -1
                ? Option.None <double>()
                : Option.Some(savedTrade.MaximumAdverseExcursion);

            MaximumFavourableExcursionPoints = savedTrade.MaximumFavourableExcursion == -1
                ? Option.None <double>()
                : Option.Some(savedTrade.MaximumFavourableExcursion);

            CalculateResult();
        }
コード例 #2
0
        private void UpdateGapFilledFlags()
        {
            for (var i = 0; i < DailyCandles.Count; i++)
            {
                if (DailyCandles[i].Gap.GapFillPercentage == 100)
                {
                    DailyCandles[i].Gap.HasGapBeenFilled = true;
                    DailyCandles[i].Gap.GapFillDate      = Option.Some(DailyCandles[i].Date);
                }
                else
                {
                    if (DailyCandles[i].Gap.GapPoints > 0)
                    {
                        for (var j = i + 1; j < DailyCandles.Count; j++)
                        {
                            if (DailyCandles[j].Low < DailyCandles[i].Open - DailyCandles[i].Gap.GapPoints)
                            {
                                DailyCandles[i].Gap.HasGapBeenFilled = true;
                                DailyCandles[i].Gap.GapFillDate      = Option.Some(DailyCandles[j].Date);
                                break;
                            }
                        }
                    }
                    else
                    {
                        for (var j = i + 1; j < DailyCandles.Count; j++)
                        {
                            if (DailyCandles[j].High > DailyCandles[i].Open - DailyCandles[i].Gap.GapPoints)
                            {
                                DailyCandles[i].Gap.HasGapBeenFilled = true;
                                DailyCandles[i].Gap.GapFillDate      = Option.Some(DailyCandles[j].Date);
                                break;
                            }
                        }
                    }
                }

                if (!DailyCandles[i].Gap.HasGapBeenFilled)
                {
                    UnfilledGaps.Add(DailyCandles[i].Gap);
                }
            }
        }
コード例 #3
0
ファイル: Trade.cs プロジェクト: Andrew-Biggins/GapTrader
        private void CalculateResult()
        {
            StopSize        = Math.Abs(OpenLevel - StopLevel);
            RiskRewardRatio = Math.Abs(Target - StrategyEntryLevel) / StopSize;

            CloseLevel.IfExistsThen(x =>
            {
                ResultInR    = Option.Some(Math.Abs(x - OpenLevel) / StopSize);
                PointsProfit = Direction == TradeDirection.Long
                    ? Option.Some(x - OpenLevel)
                    : Option.Some(OpenLevel - x);
            });

            MaximumAdverseExcursionPoints.IfExistsThen(x =>
            {
                MaximumAdverseExcursionPercentageOfStop = Option.Some(x / StopSize);
            });

            MaximumFavourableExcursionPoints.IfExistsThen(x =>
            {
                PointsProfit.IfExistsThen(y =>
                {
                    if (y > 0)
                    {
                        PointsProfitPercentageOfMaximumFavourableExcursion = Option.Some(y / x);
                        UnrealisedProfitPoints = Option.Some(x - y);
                    }
                    else
                    {
                        UnrealisedProfitPoints = Option.Some(x);
                    }

                    UnrealisedProfitPoints.IfExistsThen(z =>
                    {
                        UnrealisedProfitCash = Option.Some(z * Size);
                    });
                });
            });

            PointsProfit.IfExistsThen(x => { CashProfit = Option.Some(Size * x); });
        }
コード例 #4
0
        public Optional <string> OpenSaveDialog(object sender, string fileName, string filter)
        {
            var result = Option.None <string>();

            _context.Send(_ =>
            {
                var saveFileDialog = new SaveFileDialog
                {
                    Filter   = filter,
                    Title    = "Save Data",
                    FileName = fileName
                };

                if (saveFileDialog.ShowDialog() != false)
                {
                    result = Option.Some(saveFileDialog.FileName);
                }
            });

            return(result);
        }
コード例 #5
0
        internal static Optional <ITrade> AttemptTrade(IEnumerable <BidAskCandle> candles, double entry, double stop,
                                                       double target, TimeSpan startTime, TimeSpan endTime, double risk, bool trialStop, double trialedStopSize)
        {
            var    executed     = false;
            var    openTime     = DateTime.MaxValue;
            var    lastCandle   = new BidAskCandle(new DateTime(1, 1, 1), 1, 1, 1, 1, 1, Timezone.Uk);
            double openLevel    = 0;
            var    stopSize     = Math.Abs(entry - stop);
            var    positionSize = risk / stopSize;
            var    direction    = target > stop ? TradeDirection.Long : TradeDirection.Short;

            var high = double.NegativeInfinity;
            var low  = double.PositiveInfinity;

            var originalStop               = stop;
            var maximumAdverseExcursion    = 0.0;
            var maximumFavourableExcursion = 0.0;

            var stopTrailed = false;

            foreach (var candle in candles)
            {
                if (candle.DateTime.TimeOfDay >= startTime && candle.DateTime.TimeOfDay <= endTime)
                {
                    if (direction == TradeDirection.Long)
                    {
                        if (trialStop && executed)
                        {
                            if (candle.BidOpen > high)
                            {
                                high = candle.BidOpen;
                            }

                            // Trail stop only if in profit by at least the size of the trailed stop
                            if (high > stop + trialedStopSize && high > openLevel + trialedStopSize)
                            {
                                stop        = candle.BidOpen - trialedStopSize;
                                stopTrailed = true;
                            }
                        }

                        // When not starting at the first candle of the day,
                        // if the first candle opens past the initial intended entry (positive slippage),
                        // enter the trade on the open of that candle and update stop level accordingly
                        if (candle.AskOpen <= entry && !executed)
                        {
                            openLevel    = candle.AskOpen;
                            stop         = openLevel - stopSize;
                            originalStop = openLevel - stopSize;
                            executed     = true;
                            openTime     = candle.DateTime;
                        }

                        if (candle.AskLow < entry && !executed)
                        {
                            openLevel = entry;
                            executed  = true;
                            openTime  = candle.DateTime;
                        }

                        if (executed)
                        {
                            var adverseExcursion = openLevel - candle.AskLow;

                            if (adverseExcursion > maximumAdverseExcursion)
                            {
                                maximumAdverseExcursion = adverseExcursion;
                            }

                            var favourableExcursion = candle.BidHigh - openLevel;

                            if (favourableExcursion > maximumAdverseExcursion)
                            {
                                maximumFavourableExcursion = favourableExcursion;
                            }

                            // Ensure MFA is 100% if target is hit
                            if (candle.BidHigh > target)
                            {
                                maximumFavourableExcursion = target - openLevel;
                            }
                        }

                        if (candle.BidLow < stop && executed)
                        {
                            // Ensure MAE is 100% if full original stop is hit
                            if (!stopTrailed)
                            {
                                maximumAdverseExcursion = stopSize;
                            }

                            return(Option.Some((ITrade) new Trade(entry, originalStop, target, openLevel, Option.Some(stop), openTime, Option.Some(candle.DateTime), positionSize, Option.Some(maximumAdverseExcursion), Option.Some(maximumFavourableExcursion))));
                        }

                        if (candle.BidHigh > target && executed)
                        {
                            return(Option.Some((ITrade) new Trade(entry, originalStop, target, openLevel, Option.Some(target), openTime, Option.Some(candle.DateTime), positionSize, Option.Some(maximumAdverseExcursion), Option.Some(maximumFavourableExcursion))));
                        }
                    }
                    else if (direction == TradeDirection.Short)
                    {
                        if (trialStop && executed)
                        {
                            if (candle.AskOpen < low)
                            {
                                low = candle.AskOpen;
                            }

                            if (low < stop - trialedStopSize && low < openLevel - trialedStopSize)
                            {
                                stop        = candle.AskOpen + trialedStopSize;
                                stopTrailed = true;
                            }
                        }

                        // See above comment on opposite direction trade
                        if (candle.BidOpen >= entry && !executed)
                        {
                            openLevel    = candle.BidOpen;
                            stop         = openLevel + stopSize;
                            originalStop = openLevel + stopSize;
                            executed     = true;
                            openTime     = candle.DateTime;
                        }

                        if (candle.BidHigh > entry && !executed)
                        {
                            openLevel = entry;
                            executed  = true;
                            openTime  = candle.DateTime;
                        }

                        if (executed)
                        {
                            var adverseExcursion = candle.BidHigh - openLevel;

                            if (adverseExcursion > maximumAdverseExcursion)
                            {
                                maximumAdverseExcursion = adverseExcursion;
                            }

                            var favourableExcursion = openLevel - candle.AskLow;

                            if (favourableExcursion > maximumAdverseExcursion)
                            {
                                maximumFavourableExcursion = favourableExcursion;
                            }

                            // Ensure MFA is 100% if target is hit
                            if (candle.AskLow < target)
                            {
                                maximumFavourableExcursion = openLevel - target;
                            }
                        }

                        if (candle.AskHigh > stop && executed)
                        {
                            // Ensure MAE is 100% if full original stop is hit
                            if (!stopTrailed)
                            {
                                maximumAdverseExcursion = stopSize;
                            }

                            return(Option.Some((ITrade) new Trade(entry, originalStop, target, openLevel, Option.Some(stop), openTime, Option.Some(candle.DateTime), positionSize, Option.Some(maximumAdverseExcursion), Option.Some(maximumFavourableExcursion))));
                        }

                        if (candle.AskLow < target && executed)
                        {
                            return(Option.Some((ITrade) new Trade(entry, originalStop, target, openLevel, Option.Some(target), openTime, Option.Some(candle.DateTime), positionSize, Option.Some(maximumAdverseExcursion), Option.Some(maximumFavourableExcursion))));
                        }
                    }

                    lastCandle = candle;
                }
            }

            if (!executed)
            {
                return(Option.None <ITrade>());
            }

            // When trade is executed but neither stop or target is hit close trade at close level of last candle
            double close;

            close = direction == TradeDirection.Long ? lastCandle.BidClose : lastCandle.AskClose;

            return(Option.Some((ITrade) new Trade(entry, originalStop, target, entry, Option.Some(close), openTime, Option.Some(lastCandle.DateTime), positionSize, Option.Some(maximumAdverseExcursion), Option.Some(maximumFavourableExcursion))));
        }