Esempio n. 1
0
        internal void CloseOpenTrade(PortfolioHistoricalTradeVM trade, int openTradesIndex)
        {
            if (Options.AssetExposureBars)
            {
                var longAssetBar  = GetAssetExposureBar(trade.LongAsset, openTime);
                var shortAssetBar = GetAssetExposureBar(trade.ShortAsset, openTime);

                if (Options.JournalLevel >= 1)
                {
                    Console.WriteLine($"{trade.Trade.EntryTime} CLOSE  LONG {trade.LongAsset} x {trade.LongVolumeAtEntry}  |  SHORT {trade.ShortAsset} x {trade.ShortVolumeAtEntry}");
                }

                longAssetBar.Close  -= trade.LongVolumeAtEntry;
                shortAssetBar.Close += trade.ShortVolumeAtEntry;
            }

            OpenTrades.RemoveAt(openTradesIndex);

            CurrentBalance += trade.Trade.NetProfit / trade.Component.BacktestResult.InitialBalance;

            if (Options.ComponentExposureBars)
            {
                trade.Component.CloseTrade(trade.Trade);
            }
        }
Esempio n. 2
0
        internal void EnterOpenTrade(PortfolioHistoricalTradeVM trade)
        {
#if DEBUG
            if (Options.Verbosity >= 4)
            {
                Console.WriteLine(trade.Trade.DumpProperties());
            }
#endif
            //var symbol1 = trade.Component.BacktestResult.Symbol;
            var symbol = trade.Trade.SymbolCode;

            string longAsset, shortAsset;

            if (Options.AssetExposureBars)
            {
                if (trade.Component.IsMultiSymbol)
                {
                    (longAsset, shortAsset) = AssetNameResolver.ResolvePair(symbol);
                    if (trade.LongAsset == null || trade.ShortAsset == null)
                    {
                        throw new AnalysisException($"Could not resolve long and short components of symbol {symbol}");
                    }
                }
                else
                {
                    if (trade.Component.LongAsset == null)
                    {
                        throw new AnalysisException($"Could not resolve long and short components of symbol {symbol}");
                    }
                    longAsset  = trade.LongAsset = trade.Component.LongAsset;
                    shortAsset = trade.ShortAsset = trade.Component.ShortAsset;
                }

                //Console.WriteLine($"EnterOpenTrade | {symbol} | {trade.LongAsset} | {trade.ShortAsset}");


                var longAssetBar  = GetAssetExposureBar(longAsset, openTime);
                var shortAssetBar = GetAssetExposureBar(shortAsset, openTime);

                trade.PopulateEntryVolumes();

                if (Options.JournalLevel >= 1)
                {
                    Console.WriteLine($"{trade.Trade.EntryTime} OPEN   LONG {longAsset} x {trade.LongVolumeAtEntry}  |  SHORT {shortAsset} x {trade.ShortVolumeAtEntry}");
                }

                longAssetBar.Close  += trade.LongVolumeAtEntry;
                shortAssetBar.Close -= trade.ShortVolumeAtEntry;
            }
            OpenTrades.Add(trade);
            if (Options.ComponentExposureBars)
            {
                trade.Component.OpenTrade(trade.Trade);
            }
        }
Esempio n. 3
0
        /// <param name="trade"></param>
        /// <param name="sim"></param>
        /// <returns>Returns negative numbers for Sell trades.</returns>
        public static double NormalizeVolume(PortfolioHistoricalTradeVM trade, PortfolioSimulation sim, VolumeNormalizationOptions normalizationOptions = null)
        {
            // Note: Volume is used here instead of NetVolume, to have positive volumes for both buy and sell trades
            var normalizedTradeVolume = NormalizeVolumeSource(sim, trade.Component, trade.Trade.Volume);

#if DEBUG
            if (sim.Options.Verbosity >= 5)
            {
                Console.WriteLine($"[normalize] {trade.Trade.SymbolCode} normalized volume source from ({trade.Trade.TradeType.ToString()}) {trade.Trade.Volume} to {normalizedTradeVolume}");
            }
#endif


            if ((normalizationOptions?.MaxMode ?? sim.Options.VolumeNormalization.MaxMode).Value != VolumeNormalizationTargetMode.None)
            {
                double max = normalizationOptions?.Max ?? sim.Options.VolumeNormalization.Max ?? trade.Component.MaxAbsoluteVolume;

                //switch (mode ?? sim.Options.VolumeNormalization.VolumeNormalizationTargetMax)
                //{
                //    case PortfolioNormalizationTargetMaxMode.None:
                //        //var componentMaxNormalizedVolume = NormalizeVolumeSource(sim, trade.Component, trade.Component.MaxAbsoluteVolume);
                //        //max = componentMaxNormalizedVolume;
                //        //max =
                //        break;
                //    case PortfolioNormalizationTargetMaxMode.ToConstant:
                //        max = ;
                //        break;
                //    //case PortfolioNormalizationTargetMaxMode.
                //    //case PortfolioNormalizationTargetMaxMode.ScaleToMinTradeVolume:
                //    //    max =
                //    //    value =
                //    //    if (trade.Trade.TradeType == TradeType.Sell) value *= -1;
                //    //    break;
                //    //case PortfolioNormalizationTargetMaxMode.ToBacktestMaxTradeSize:
                //    //    value = trade.Trade.Volume / trade.Component.MaxAbsoluteVolume;
                //    //    if (trade.Trade.TradeType == TradeType.Sell) value *= -1;
                //    //    break;
                //    ////case PortfolioNormalizationMode.ToBacktestConfiguredMaxTradeSize:
                //    ////    throw new NotImplementedException();
                //    ////    break;
                //    default:
                //        //case PortfolioNormalizationMode.Unspecified:
                //        throw new ArgumentException(nameof(sim.Options.VolumeNormalization.VolumeNormalizationTargetMax));
                //}

                switch (sim.Options.VolumeNormalization.Curve)
                {
                case PortfolioNormalizationCurveType.Linear:
                    normalizedTradeVolume = trade.Trade.TradeType == TradeType.Buy ? trade.Trade.Volume : -trade.Trade.Volume;
                    break;

                case PortfolioNormalizationCurveType.Step:
                    normalizedTradeVolume = normalizedTradeVolume >= sim.Options.VolumeNormalization.StepThreshold ? max : 0;
                    break;

                case PortfolioNormalizationCurveType.EaseIn:
                {
                    double normalizedTo1 = normalizedTradeVolume / max;
                    normalizedTradeVolume = max * Math.Pow(normalizedTo1, sim.Options.VolumeNormalization.EasingExponent ?? VolumeNormalizationOptions.DefaultEasingExponent);
                    break;
                }

                case PortfolioNormalizationCurveType.EaseOut:
                {
                    double normalizedTo1 = normalizedTradeVolume / max;
                    normalizedTradeVolume = max * Math.Pow(1 - (1 - normalizedTo1), sim.Options.VolumeNormalization.EasingExponent ?? VolumeNormalizationOptions.DefaultEasingExponent);
                    break;
                }

                //case PortfolioNormalizationCurveType.Unspecified:
                default:
                    break;
                }
            }

            if (trade.Trade.TradeType == TradeType.Sell)
            {
                normalizedTradeVolume *= -1;
            }

#if DEBUG
            if (sim.Options.Verbosity >= 0)
            {
                if (trade.Trade.Volume != 1)
                {
                    Console.WriteLine($"[NORMALIZE] {trade.Trade.SymbolCode} normalized volume from ({trade.Trade.TradeType.ToString()}) {trade.Trade.Volume} to {normalizedTradeVolume}   (final)");
                }
            }
#endif

            return(normalizedTradeVolume);
        }