Example #1
0
        private void BuyAsset(IndexedCandle indexedCandle, decimal premium, IDictionary <IList <Candle>, decimal> assetCashMap, IList <Transaction> transactions)
        {
            if (assetCashMap.TryGetValue(indexedCandle.Candles, out decimal cash))
            {
                var nextCandle = indexedCandle.Next;
                int quantity   = Convert.ToInt32(Math.Floor((cash - premium) / nextCandle.Open));

                decimal cashOut = nextCandle.Open * quantity + premium;
                assetCashMap[indexedCandle.Candles] -= cashOut;

                transactions.Add(new Transaction(indexedCandle.Candles, nextCandle.Index, nextCandle.DateTime, TransactionType.Buy, quantity, cashOut));
                OnBought?.Invoke(indexedCandle.Candles, nextCandle.Index, nextCandle.DateTime, nextCandle.Open, quantity, cashOut, assetCashMap[indexedCandle.Candles]);
            }
        }
Example #2
0
        private void SellAsset(IndexedCandle indexedCandle, decimal premium, IDictionary <IList <Candle>, decimal> assetCashMap, IList <Transaction> transactions)
        {
            if (assetCashMap.TryGetValue(indexedCandle.Candles, out _))
            {
                var nextCandle      = indexedCandle.Next;
                var lastTransaction = transactions.LastOrDefault(t => t.Candles.Equals(indexedCandle.Candles));
                if (lastTransaction.Type == TransactionType.Sell)
                {
                    return;
                }

                decimal cashIn  = nextCandle.Open * lastTransaction.Quantity - premium;
                decimal plRatio = (cashIn - lastTransaction.AbsoluteCashFlow) / lastTransaction.AbsoluteCashFlow;
                assetCashMap[indexedCandle.Candles] += cashIn;

                transactions.Add(new Transaction(indexedCandle.Candles, nextCandle.Index, nextCandle.DateTime, TransactionType.Sell, lastTransaction.Quantity, cashIn));
                OnSold?.Invoke(indexedCandle.Candles, nextCandle.Index, nextCandle.DateTime, nextCandle.Open, lastTransaction.Quantity, cashIn, assetCashMap[indexedCandle.Candles], plRatio);
            }
        }
Example #3
0
        public Result RunBacktest(decimal principal, decimal premium = 1.0m, DateTime?startTime = null, DateTime?endTime = null)
        {
            if (_weightings == null || !_weightings.Any())
            {
                throw new ArgumentException("You should have at least one candle set for calculation");
            }

            // Distribute principal to each candle set
            decimal totalWeight = _weightings.Sum(w => w.Value);
            IReadOnlyDictionary <IList <Candle>, decimal> preAssetCashMap = _weightings.ToDictionary(w => w.Key, w => principal * w.Value / totalWeight);
            var assetCashMap = preAssetCashMap.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

            // Init transaction history
            var transactions = new List <Transaction>();

            // Loop with each asset
            for (int i = 0; i < _weightings.Count; i++)
            {
                var asset = assetCashMap.ElementAt(i).Key;

                var startIndex = asset.FindIndexOrDefault(c => c.DateTime >= (startTime ?? DateTime.MinValue), 0).Value;
                var endIndex   = asset.FindLastIndexOrDefault(c => c.DateTime <= (endTime ?? DateTime.MaxValue), asset.Count - 1).Value;

                for (int j = startIndex; j <= endIndex; j++)
                {
                    var indexedCandle   = new IndexedCandle(asset, j);
                    var lastTransaction = transactions.LastOrDefault(t => t.Candles.Equals(asset));
                    if (lastTransaction?.Type != TransactionType.Buy && _buyRule.IsValid(indexedCandle))
                    {
                        BuyAsset(indexedCandle, premium, assetCashMap, transactions);
                    }
                    else if (lastTransaction?.Type != TransactionType.Sell && _sellRule.IsValid(indexedCandle))
                    {
                        SellAsset(indexedCandle, premium, assetCashMap, transactions);
                    }
                }
            }

            return(new Result(preAssetCashMap, assetCashMap, transactions));
        }
Example #4
0
 public static bool IsEmaOscBearish(this IndexedCandle ic, int periodCount1, int periodCount2)
 => ic.Get <ExponentialMovingAverageOscillatorTrend>(periodCount1, periodCount2)[ic.Index] == Trend.Bearish;
Example #5
0
 public static decimal?PriceChange(this IndexedCandle ic)
 => ic.Get <ClosePriceChange>()[ic.Index];
Example #6
0
 public static bool IsSmaBearish(this IndexedCandle ic, int periodCount)
 => ic.Get <SimpleMovingAverageTrend>(periodCount)[ic.Index] == Trend.Bearish;
Example #7
0
 public static bool IsAboveSma(this IndexedCandle ic, int periodCount)
 => ic.Get <IsAboveSimpleMovingAverage>(periodCount)[ic.Index] ?? false;
Example #8
0
 public static bool IsFullStoOverbought(this IndexedCandle ic, int periodCount, int smaPeriodCountK, int smaPeriodCountD)
 => ic.Get <StochasticsOvertrade.Full>(periodCount, smaPeriodCountK, smaPeriodCountD)[ic.Index] == Overtrade.SeverelyOverbought;
Example #9
0
 public static bool IsLowest(this IndexedCandle ic, int periodCount)
 => ic.Get <IsLowestPrice>(periodCount)[ic.Index] ?? false;
Example #10
0
 public static bool IsSlowStoOscBearish(this IndexedCandle ic, int periodCount, int smaPeriodCountD)
 => ic.Get <StochasticsOscillatorTrend.Slow>(periodCount, smaPeriodCountD)[ic.Index] == Trend.Bearish;
Example #11
0
 public static bool IsFullStoOscBullish(this IndexedCandle ic, int periodCount, int smaPeriodCountK, int smaPeriodCountD)
 => ic.Get <StochasticsOscillatorTrend.Full>(periodCount, smaPeriodCountK, smaPeriodCountD)[ic.Index] == Trend.Bullish;
Example #12
0
 public static bool IsFastStoOversold(this IndexedCandle ic, int periodCount, int smaPeriodCount)
 => ic.Get <StochasticsOvertrade.Fast>(periodCount, smaPeriodCount)[ic.Index].Tick == Overtrade.SeverelyOversold;
Example #13
0
 public static bool IsFastStoBearishCross(this IndexedCandle ic, int periodCount, int smaPeriodCount)
 => ic.Get <StochasticsCrossover.Fast>(periodCount, smaPeriodCount)[ic.Index].Tick == Crossover.BearishCrossover;
Example #14
0
 public static decimal?PricePercentageChange(this IndexedCandle ic)
 => ic.Get <ClosePricePercentageChange>()[ic.Index].Tick;
Example #15
0
 public static bool IsFastStoOscBearish(this IndexedCandle ic, int periodCount, int smaPeriodCount)
 => ic.Get <StochasticsOscillatorTrend.Fast>(periodCount, smaPeriodCount)[ic.Index].Tick == Trend.Bearish;
Example #16
0
 public static bool IsObvBearish(this IndexedCandle ic)
 => ic.Get <OnBalanceVolumeTrend>()[ic.Index] == Trend.Bearish;
Example #17
0
 public static bool IsInBbRange(this IndexedCandle ic, int periodCount, int sdCount)
 => ic.Get <BollingerBandsInRange>(periodCount, sdCount)[ic.Index] == Overboundary.InRange;
Example #18
0
 public static bool IsSmaBullishCross(this IndexedCandle ic, int periodCount1, int periodCount2)
 => ic.Get <SimpleMovingAverageCrossover>(periodCount1, periodCount2)[ic.Index] == Crossover.BullishCrossover;
Example #19
0
 public static bool IsRsiOversold(this IndexedCandle ic, int periodCount)
 => ic.Get <RelativeStrengthIndexOvertrade>(periodCount)[ic.Index] == Overtrade.Oversold;
Example #20
0
 public static bool IsEmaBearishCross(this IndexedCandle ic, int periodCount1, int periodCount2)
 => ic.Get <ExponentialMovingAverageCrossover>(periodCount1, periodCount2)[ic.Index] == Crossover.BearishCrossover;
Example #21
0
 public static bool IsSlowStoOversold(this IndexedCandle ic, int periodCount, int smaPeriodCountD)
 => ic.Get <StochasticsOvertrade.Slow>(periodCount, smaPeriodCountD)[ic.Index] == Overtrade.SeverelyOversold;
Example #22
0
 public static bool IsMacdBearishCross(this IndexedCandle ic, int emaPeriodCount1, int emaPeriodCount2, int demPeriodCount)
 => ic.Get <MovingAverageConvergenceDivergenceCrossover>(emaPeriodCount1, emaPeriodCount2, demPeriodCount)[ic.Index] == Crossover.BearishCrossover;
Example #23
0
 public static bool IsAboveEma(this IndexedCandle ic, int periodCount)
 => ic.Get <IsAboveExponentialMovingAverage>(periodCount)[ic.Index] ?? false;
Example #24
0
 public static bool IsFullStoBullishCross(this IndexedCandle ic, int periodCount, int smaPeriodCountK, int smaPeriodCountD)
 => ic.Get <StochasticsCrossover.Full>(periodCount, smaPeriodCountK, smaPeriodCountD)[ic.Index] == Crossover.BullishCrossover;
Example #25
0
 public static bool IsSmaOscBullish(this IndexedCandle ic, int periodCount1, int periodCount2)
 => ic.Get <SimpleMovingAverageOscillatorTrend>(periodCount1, periodCount2)[ic.Index] == Trend.Bullish;
Example #26
0
 public static bool IsSlowStoBearishCross(this IndexedCandle ic, int periodCount, int smaPeriodCountD)
 => ic.Get <StochasticsCrossover.Slow>(periodCount, smaPeriodCountD)[ic.Index] == Crossover.BearishCrossover;
Example #27
0
 public static bool IsEmaBearish(this IndexedCandle ic, int periodCount)
 => ic.Get <ExponentialMovingAverageTrend>(periodCount)[ic.Index] == Trend.Bearish;
Example #28
0
 public static bool IsCandlesBearish(this IndexedCandle ic)
 => ic.Get <ClosePriceChangeTrend>()[ic.Index] == Trend.Bearish;
Example #29
0
 public static bool IsMacdOscBearish(this IndexedCandle ic, int emaPeriodCount1, int emaPeriodCount2, int demPeriodCount)
 => ic.Get <MovingAverageConvergenceDivergenceOscillatorTrend>(emaPeriodCount1, emaPeriodCount2, demPeriodCount)[ic.Index] == Trend.Bearish;
Example #30
0
 public static bool IsAccumDistBearish(this IndexedCandle ic)
 => ic.Get <AccumulationDistributionLineTrend>()[ic.Index] == Trend.Bearish;