private bool isResultsatisfy(TradingResult fResult)
 {
     if (fResult.Profit < MinProfit || fResult.Risk > MaxRisk || fResult.WinRate < MinWinRate)
     {
         return(false);
     }
     return(true);
 }
        private TradingResult Simulate(TradingRule tradingRule)
        {
            TradingResult             tradingResult = new TradingResult();
            List <SimulatitonPartern> simulateds    = new List <SimulatitonPartern>();
            POS        pOS   = new POS();
            int        index = 1;
            bool       isBuyTradingCommand = false;
            List <int> tidBP = new List <int>();

            if (tradingRule.BP?.TIDSet.Count() > 0)
            {
                tidBP.AddRange(tradingRule.BP?.TIDSet);
            }
            List <int> tidSP = new List <int>();

            if (tradingRule.SP?.TIDSet.Count() > 0)
            {
                tidSP.AddRange(tradingRule.SP?.TIDSet);
            }
            //

            // check if exist at least one complete trading order || Sell trading Command and existing sell transactions when buy transaction end.
            while ((tidBP?.Count > 0 && tidSP?.Count > 0) || (isBuyTradingCommand && tidSP?.Count > 0))
            {
                // generate all Trading order and Hold position
                SimulatitonPartern sm = new SimulatitonPartern();
                sm.TradingOrder  = new TradingOrder();
                sm.TradingResult = new TradingResult();
                sm.HPOS          = new POS();
                if (index == 1)
                {
                    sm.No = index;
                    sm.TradingOrder.tc = tradingRule.topPriority == TP.SF ? TradingCommands.Sell : TradingCommands.Buy;

                    sm.TradingOrder.qty = 1;
                    //transaction start at 0-1-2, tid start at 1-2-3
                    sm.TradingOrder.price = sm.TradingOrder.tc == TradingCommands.Buy ? transactions[tidBP[0] - 1].Price : transactions[tidSP[0] - 1].Price;
                    sm.TID         = sm.TradingOrder.tc == TradingCommands.Buy ? tidBP[0] : tidSP[0];
                    sm.HPOS.mp     = sm.TradingOrder.tc == TradingCommands.Buy ? MarketPosition.Long : MarketPosition.Short;
                    sm.HPOS.hqty   = 1;
                    sm.HPOS.hprice = sm.TradingOrder.price;
                    //
                    isBuyTradingCommand = sm.TradingOrder.tc == TradingCommands.Buy ? true : false;
                }
                else
                {
                    if (isBuyTradingCommand)
                    {
                        //simutaled trading is sell
                        sm.No = index;
                        sm.TradingOrder.tc    = TradingCommands.Sell;
                        sm.TradingOrder.qty   = 1;
                        sm.TradingOrder.price = transactions[tidSP[0] - 1].Price;
                        sm.TID              = tidSP[0];
                        sm.HPOS.mp          = MarketPosition.Short;
                        sm.HPOS.hqty        = 1;
                        sm.HPOS.hprice      = sm.TradingOrder.price;
                        isBuyTradingCommand = false;
                    }
                    else
                    {
                        //simutaled trading is buy
                        sm.No = index;
                        sm.TradingOrder.tc    = TradingCommands.Buy;
                        sm.TradingOrder.qty   = 1;
                        sm.TradingOrder.price = transactions[tidBP[0] - 1].Price;
                        sm.TID              = tidBP[0];
                        sm.HPOS.mp          = MarketPosition.Long;
                        sm.HPOS.hqty        = 1;
                        sm.HPOS.hprice      = sm.TradingOrder.price;
                        isBuyTradingCommand = true;
                    }
                }

                if (sm.TradingOrder.tc == TradingCommands.Buy)
                {
                    if (tidSP[0] == tidBP[0])
                    {
                        tidSP.RemoveAt(0);
                    }
                    tidBP.RemoveAt(0);
                }
                else
                {
                    // avoid empty buy pattern
                    if (tidBP.Count() > 0 && tidBP[0] == tidSP[0])
                    {
                        tidBP.RemoveAt(0);
                    }
                    tidSP.RemoveAt(0);
                }

                index++;
                simulateds.Add(sm);
            }

            for (int i = 0; i < simulateds.Count; i++)
            {
                // set Netprofit
                // Last record don't have Netprofit
                simulateds[i].NP = i == (simulateds.Count - 1) ? 0 : simulateds[i].HPOS.mp == MarketPosition.Long ?
                                   simulateds[i + 1].HPOS.hprice - simulateds[i].HPOS.hprice - MAX_SPAN * FEE :
                                   simulateds[i].HPOS.hprice - simulateds[i + 1].HPOS.hprice - MAX_SPAN * FEE;

                // set Consecutive loss
                //Last record don't have Netprofit
                simulateds[i].CLoss = i == 0 ? simulateds[i].NP : simulateds[i].NP + simulateds[i - 1].CLoss;

                // Closs could not be positive && Last record don't have Netprofit
                simulateds[i].CLoss = (simulateds[i].CLoss > 0) || i == (simulateds.Count - 1) ? 0 : simulateds[i].CLoss;


                // Set Run UP && Draw Down
                if (i == simulateds.Count - 1)
                {
                    if (isExistsTID(simulateds[i].TID))
                    {
                        simulateds[i].DD = simulateds[i].HPOS.mp == MarketPosition.Short ? 0 :
                                           i == 0 ? 0 + Math.Min(simulateds[i].HPOS.hprice, GetTransactionPrice(simulateds[i].TID + 1)) - simulateds[i].HPOS.hprice :
                                           simulateds[i - 1].CLoss + Math.Min(simulateds[i].HPOS.hprice, GetTransactionPrice(simulateds[i].TID + 1)) - simulateds[i].HPOS.hprice;

                        simulateds[i].RU = simulateds[i].HPOS.mp == MarketPosition.Long ? 0 :
                                           i == 0 ? 0 - Math.Max(simulateds[i].HPOS.hprice, GetTransactionPrice(simulateds[i].TID + 1)) + simulateds[i].HPOS.hprice :
                                           simulateds[i - 1].CLoss - Math.Max(simulateds[i].HPOS.hprice, GetTransactionPrice(simulateds[i].TID + 1)) + simulateds[i].HPOS.hprice;
                    }
                }
                else
                {
                    simulateds[i].DD = simulateds[i].HPOS.mp == MarketPosition.Short ? 0 :
                                       i == 0 ? 0 + Math.Min(simulateds[i].HPOS.hprice, simulateds[i + 1].HPOS.hprice) - simulateds[i].HPOS.hprice :
                                       simulateds[i - 1].CLoss + Math.Min(simulateds[i].HPOS.hprice, simulateds[i + 1].HPOS.hprice) - simulateds[i].HPOS.hprice;
                    simulateds[i].RU = simulateds[i].HPOS.mp == MarketPosition.Long ? 0 :
                                       i == 0 ? 0 - Math.Max(simulateds[i].HPOS.hprice, simulateds[i + 1].HPOS.hprice) + simulateds[i].HPOS.hprice :
                                       simulateds[i - 1].CLoss - Math.Max(simulateds[i].HPOS.hprice, simulateds[i + 1].HPOS.hprice) + simulateds[i].HPOS.hprice;
                }

                // Set Profit
                simulateds[i].TradingResult.Profit = i == (simulateds.Count - 1) ? 0 : simulateds.Sum(o => o.NP);

                //Set Risk
                simulateds[i].TradingResult.Risk = i == 0 ? new List <double>()
                {
                    Absolute(simulateds[i].CLoss), Absolute(simulateds[i].DD), Absolute(simulateds[i].RU)
                }.Max() :
                new List <double>()
                {
                    Absolute(simulateds[i].CLoss), Absolute(simulateds[i].DD), Absolute(simulateds[i].RU), Absolute(simulateds[i - 1].TradingResult.Risk)
                }.Max();

                //Set WinRate
                simulateds[i].TradingResult.WinRate = i == (simulateds.Count - 1) ? 0 : Math.Round(simulateds.Where(o => o.NP > 0).Count() * 1.0 / simulateds[i].No * 100, 0);
            }

            tradingResult.Profit  = simulateds[simulateds.Count - 2].TradingResult.Profit;
            tradingResult.Risk    = isExistsTID(simulateds[simulateds.Count - 1].TID) ? simulateds[simulateds.Count - 1].TradingResult.Risk : simulateds[simulateds.Count - 2].TradingResult.Risk;
            tradingResult.WinRate = simulateds[simulateds.Count - 2].TradingResult.WinRate;

            return(tradingResult);
        }
        private void GenSP(Pattern BP, Pattern prefix, int index, int interval)
        {
            Pattern pre = null;

            if (prefix != null)
            {
                pre        = new Pattern();
                pre.name   = prefix.name;
                pre.TIDSet = prefix.TIDSet.ToList();
            }

            // pattern X = 𝑥1(𝑖1) 𝑥2(𝑖2)⋅⋅⋅𝑥𝑗(𝑖𝑗), where j > 0 and 0 ≥ 𝑖𝑗 ≥ (1 − maxspan)
            if (interval >= MAX_SPAN)
            {
                return;
            }
            for (int i = index; i < oneItemList.Count; i++)
            {
                Pattern SP = new Pattern();
                SP.name   = oneItemList[i].name;
                SP.TIDSet = oneItemList[i].TIDSet.ToList();

                SP = Shift(SP, interval);
                SP = Join(pre, SP);

                //Debug.WriteLine("------------- GenSP ----------------");
                //foreach (var item in SP.TIDSet)
                //{
                //    Debug.WriteLine(SP.name + " " + item + "  ");
                //}
                //Debug.WriteLine("");

                // check if exist at least one transaction
                if (SP.TIDSet.Count() >= minSup)
                {
                    if (ComparePattern(BP, SP) != 1 && BP.TIDSet.Count() > 0 && SP.TIDSet.Count > 0)
                    {
                        List <TradingRule> lstTradingRule = new List <TradingRule>();
                        lstTradingRule = RuleGenerator(BP, SP);
                        if (BP.name == "A(0)C(-1)")
                        {
                            var x = 0;
                        }
                        foreach (var trRule in lstTradingRule)
                        {
                            TradingResult tradingResult = Simulate(trRule);
                            if (isResultsatisfy(tradingResult))
                            {
                                trRule.tradingResult = tradingResult;
                                tradingRules.Add(trRule);
                            }
                        }
                        GenSP(BP, SP, i + 1, interval);
                    }
                }
            }

            if (prefix != null)
            {
                GenSP(BP, pre, 0, interval + 1);
            }
        }