Esempio n. 1
0
        private double[] computeNetValue(List <StockTransaction> etf, double[] longSignal, double[] shortSignal, ref List <OneByOneTransaction> data)
        {
            double[] netvalue = new double[etf.Count()];
            data = new List <OneByOneTransaction>();
            OneByOneTransaction transaction = new OneByOneTransaction();
            double nv             = 0;
            double position       = 0;
            double cash           = 1;
            double stopPrice      = 0;
            double shortStopPrice = 0;
            double stopRatio      = 0.95;
            double shortStopRatio = 1.05;
            double slipRatio      = 0.0002;
            double count          = 0;

            for (int i = 0; i < etf.Count(); i++)
            {
                DateTime time       = etf[i].DateTime;
                double   stockPrice = etf[i].Close;
                if (time.TimeOfDay > new TimeSpan(14, 55, 00) && position != 0) //超过14点55分有仓位,强制平仓
                {
                    cash                   = cash + (stockPrice * position) - Math.Abs(stockPrice * position * slipRatio);
                    position               = 0;
                    stopPrice              = 0;
                    shortStopPrice         = 0;
                    transaction.closeTime  = time;
                    transaction.closePrice = stockPrice;
                    data.Add(transaction);
                    transaction = new OneByOneTransaction();
                }
                if (position == 0 && time.TimeOfDay < new TimeSpan(14, 45, 00) && time.TimeOfDay > new TimeSpan(9, 35, 00)) //未开仓
                {
                    if (longSignal[i] > 0)                                                                                  //开多头
                    {
                        position  = cash * (1 - slipRatio) / stockPrice;
                        cash      = 0;
                        stopPrice = stockPrice * stopRatio;
                        count++;
                        transaction           = new OneByOneTransaction();
                        transaction.openTime  = time;
                        transaction.openPrice = stockPrice;
                        transaction.position  = 1;
                    }
                    else if (shortSignal[i] < 0)//开空头
                    {
                        position       = -cash * (1 - slipRatio) / stockPrice;
                        cash           = cash - position * stockPrice;
                        shortStopPrice = stockPrice * shortStopRatio;
                        count++;
                        transaction           = new OneByOneTransaction();
                        transaction.openTime  = time;
                        transaction.openPrice = stockPrice;
                        transaction.position  = -1;
                    }
                }
                else //已开仓
                {
                    if (position > 0) //已开多仓
                    {
                        //记录追踪止损的点位
                        if (stopPrice < stockPrice * stopRatio)
                        {
                            stopPrice = stockPrice * stopRatio;
                        }
                        if (stockPrice < stopPrice || shortSignal[i] < 0) //平仓或者止损
                        {
                            cash                   = cash + stockPrice * position - Math.Abs(stockPrice * position * slipRatio);
                            position               = 0;
                            stopPrice              = 0;
                            transaction.closeTime  = time;
                            transaction.closePrice = stockPrice;
                            data.Add(transaction);
                            transaction = new OneByOneTransaction();
                        }
                        if (position == 0 && shortSignal[i] == -2 && time.TimeOfDay < new TimeSpan(14, 45, 00)) //平仓之后反手
                        {
                            position       = -cash * (1 - slipRatio) / stockPrice;
                            cash           = cash - position * stockPrice;
                            shortStopPrice = stockPrice * shortStopRatio;
                            count++;
                            transaction           = new OneByOneTransaction();
                            transaction.openTime  = time;
                            transaction.openPrice = stockPrice;
                            transaction.position  = -1;
                        }
                    }
                    else if (position < 0) //已开空仓
                    {
                        //记录追踪止损的点位
                        if (shortStopPrice > stockPrice * shortStopRatio)
                        {
                            shortStopPrice = stockPrice * shortStopRatio;
                        }
                        if (stockPrice > shortStopPrice || longSignal[i] > 0) //平仓或者止损
                        {
                            cash                   = cash + stockPrice * position - Math.Abs(stockPrice * position * slipRatio);
                            position               = 0;
                            shortStopPrice         = 0;
                            transaction.closeTime  = time;
                            transaction.closePrice = stockPrice;
                            data.Add(transaction);
                            transaction = new OneByOneTransaction();
                        }
                        if (position == 0 && longSignal[i] == 2 && time.TimeOfDay < new TimeSpan(14, 45, 00)) //平仓之后反手
                        {
                            position  = cash * (1 - slipRatio) / stockPrice;
                            cash      = 0;
                            stopPrice = stockPrice * stopRatio;
                            count++;
                            transaction           = new OneByOneTransaction();
                            transaction.openTime  = time;
                            transaction.openPrice = stockPrice;
                            transaction.position  = 1;
                        }
                    }
                }
                nv          = cash + position * etf[i].Close;
                netvalue[i] = nv;
            }
            return(netvalue);
        }
        private bool ComputeDualTrust(List <DateTime> tradedays, List <StockTransaction> underlying, double[] signal, double[] range, double trailingParameter, ref List <OneByOneTransaction> data, ref List <netvalueDaily> netvalueList)
        {
            int    lengthOfDays             = tradedays.Count();
            double originalCash             = 10000;
            double cash                     = originalCash;
            double position                 = 0;
            double maxProfit                = 0;
            bool   tradable                 = false;
            OneByOneTransaction transaction = new OneByOneTransaction();

            for (int i = 0; i < lengthOfDays; i++)
            {
                if (range[i] < 10)
                {
                    continue;
                }
                int j     = 0;
                int index = 0;
                StockTransaction dataNow  = new StockTransaction();
                double           avgPrice = 0;
                for (j = 0; j < minutes - 5; j++)
                {
                    index   = i * minutes + j;
                    dataNow = underlying[index];
                    if (dataNow.Volume > 0)
                    {
                        tradable = true;
                    }
                    else
                    {
                        tradable = false;
                        continue;
                    }
                    avgPrice = dataNow.Amount / dataNow.Volume / multiplicator;
                    if (position == 0)          //开仓
                    {
                        if (signal[index] == 1) //开多头
                        {
                            position              = 1;
                            cash                  = cash - avgPrice - avgPrice * slipRatio;
                            transaction           = new OneByOneTransaction();
                            transaction.position  = 1;
                            transaction.openTime  = dataNow.DateTime;
                            transaction.openPrice = avgPrice;
                            maxProfit             = 0;
                        }
                        if (signal[index] == -1) //开空头
                        {
                            position              = -1;
                            cash                  = cash + avgPrice - avgPrice * slipRatio;
                            transaction           = new OneByOneTransaction();
                            transaction.position  = -1;
                            transaction.openTime  = dataNow.DateTime;
                            transaction.openPrice = avgPrice;
                            maxProfit             = 0;
                        }
                    }
                    else
                    {
                        if (position == 1)
                        {
                            if ((dataNow.Open / transaction.openPrice - 1) < maxProfit - trailingParameter)
                            {
                                cash     = cash + avgPrice - avgPrice * slipRatio;
                                position = 0;
                                transaction.closePrice  = avgPrice;
                                transaction.closeTime   = dataNow.DateTime;
                                transaction.closeStatus = "追踪止损";
                                data.Add(transaction);
                                transaction = new OneByOneTransaction();
                            }
                        }
                        if (position == -1)
                        {
                            if ((transaction.openPrice / dataNow.Open - 1) < maxProfit - trailingParameter)
                            {
                                cash     = cash - avgPrice - avgPrice * slipRatio;
                                position = 0;
                                transaction.closePrice  = avgPrice;
                                transaction.closeTime   = dataNow.DateTime;
                                transaction.closeStatus = "追踪止损";
                                data.Add(transaction);
                                transaction = new OneByOneTransaction();
                            }
                        }
                    }
                    if (position == 1)
                    {
                        if ((dataNow.Close / transaction.openPrice - 1) > maxProfit)
                        {
                            maxProfit = (dataNow.Close / transaction.openPrice - 1);
                        }
                    }
                    if (position == -1)
                    {
                        if ((transaction.openPrice / dataNow.Close - 1) > maxProfit)
                        {
                            maxProfit = (transaction.openPrice / dataNow.Close - 1);
                        }
                    }
                }

                //日内最后3分钟平仓
                j       = minutes - 3;
                index   = i * minutes + j;
                dataNow = underlying[index];
                if (dataNow.Volume > 0)
                {
                    tradable = true;
                }
                else
                {
                    tradable = false;
                }
                avgPrice = dataNow.Amount / dataNow.Volume / multiplicator;
                if (position == 1 && tradable)
                {
                    cash     = cash + avgPrice - avgPrice * slipRatio;
                    position = 0;
                    transaction.closePrice  = avgPrice;
                    transaction.closeTime   = dataNow.DateTime;
                    transaction.closeStatus = "收盘强平";
                    data.Add(transaction);
                    transaction = new OneByOneTransaction();
                }
                if (position == -1 && tradable)
                {
                    cash     = cash - avgPrice - avgPrice * slipRatio;
                    position = 0;
                    transaction.closePrice  = avgPrice;
                    transaction.closeTime   = dataNow.DateTime;
                    transaction.closeStatus = "收盘强平";
                    data.Add(transaction);
                    transaction = new OneByOneTransaction();
                }

                //计算每日收盘时候的净值
                index   = i * minutes + minutes - 1;
                dataNow = underlying[index];
                netvalueDaily nvToday = new netvalueDaily();
                nvToday.date     = dataNow.DateTime.Date;
                nvToday.netvalue = cash + position * dataNow.Close;
                netvalueList.Add(nvToday);
            }
            return(true);
        }
        //第二类布林带的使用,当价格上穿上轨1的时候买入,当下轨下穿下轨1的时候卖出
        private bool bollingerBrand2(List <StockTransaction> underlying1, List <StockTransaction> underlying2, double[] signal, int duration, List <BollingerBandwithPrice> myboll, ref List <OneByOneTransaction> data, ref List <netvalueDaily> netvalueList)
        {
            netvalueList = new List <netvalueDaily>();
            data         = new List <OneByOneTransaction>();
            OneByOneTransaction transaction = new OneByOneTransaction();
            double        position1         = 0;
            double        position2         = 0;
            double        cash              = 1;
            double        slipRatio         = 0.003;
            double        nv                = 1;
            double        trailingProfit    = 0;
            bool          trailingStop      = false;
            double        trailingParameter = 0.02;
            netvalueDaily nvToday           = new netvalueDaily();

            nvToday.netvalue = nv;
            nvToday.date     = underlying1[0].DateTime;
            bool trade  = true;
            int  length = signal.Length;

            netvalueList.Add(nvToday);
            for (int i = 1; i < length; i++)
            {
                trade = true;
                if (underlying1[i].TradeStatus != "交易" || underlying2[i].TradeStatus != "交易")
                {
                    trade = false;
                }
                double underlying1AvgPrice   = underlying1[i].AdjFactor * underlying1[i].Amount / underlying1[i].Volume;
                double underlying2AvgPrice   = underlying2[i].AdjFactor * underlying2[i].Amount / underlying2[i].Volume;
                double underlying1ClosePrice = underlying1[i].AdjFactor * underlying1[i].Close;
                double underlying2ClosePrice = underlying2[i].AdjFactor * underlying2[i].Close;
                double pairPriceYesterday    = Math.Log(underlying1[i - 1].AdjFactor * underlying1[i - 1].Close / (underlying2[i - 1].AdjFactor * underlying2[i - 1].Close));
                var    today = underlying1[i].DateTime;
                //空仓情况,看情况开仓
                if (position1 == 0 && position2 == 0 && trade == true)
                {
                    //上穿上轨1
                    if (signal[i - 1] == 3)
                    {
                        cash                  = cash * (1 - slipRatio);
                        position1             = cash / 2 / underlying1AvgPrice;
                        position2             = -cash / 2 / underlying2AvgPrice;
                        transaction.openTime  = today;
                        transaction.position  = 1;
                        transaction.openPrice = Math.Log(underlying1AvgPrice / underlying2AvgPrice);
                        trailingProfit        = 0;
                        trailingStop          = false;
                    }
                    //下穿上轨1
                    else if (signal[i - 1] == -1)
                    {
                        cash                  = cash * (1 - slipRatio);
                        position1             = -cash / 2 / underlying1AvgPrice;
                        position2             = cash / 2 / underlying2AvgPrice;
                        transaction.openTime  = today;
                        transaction.position  = -1;
                        transaction.openPrice = Math.Log(underlying1AvgPrice / underlying2AvgPrice);
                        trailingProfit        = 0;
                        trailingStop          = false;
                    }
                }
                //多头情况
                else if (position1 > 0 && position2 < 0 && trade == true)
                {
                    //追踪止损
                    if (trailingStop == true)
                    {
                        cash                   += position1 * underlying1AvgPrice * (1 - slipRatio) + position2 * underlying2AvgPrice * (1 + slipRatio);
                        position1               = 0;
                        position2               = 0;
                        transaction.closeTime   = today;
                        transaction.closePrice  = Math.Log(underlying1AvgPrice / underlying2AvgPrice);
                        transaction.closeStatus = "追踪止损";
                        data.Add(transaction);
                        transaction    = new OneByOneTransaction();
                        trailingStop   = false;
                        trailingProfit = 0;
                    }
                }
                //空头情况
                else if (position1 < 0 && position2 > 0 && trade == true)
                {
                    //追踪止损
                    if (trailingStop == true)
                    {
                        cash                   += position1 * underlying1AvgPrice * (1 + slipRatio) + position2 * underlying2AvgPrice * (1 - slipRatio);
                        position1               = 0;
                        position2               = 0;
                        transaction.closeTime   = today;
                        transaction.closePrice  = Math.Log(underlying1AvgPrice / underlying2AvgPrice);
                        transaction.closeStatus = "追踪止损";
                        data.Add(transaction);
                        transaction    = new OneByOneTransaction();
                        trailingStop   = false;
                        trailingProfit = 0;
                    }
                }
                //计算追踪止损点位
                double closePrice = Math.Log(underlying1ClosePrice / underlying2ClosePrice);
                if (position1 > 0 && position2 < 0) //多头
                {
                    if (closePrice > trailingProfit + transaction.openPrice)
                    {
                        trailingProfit = closePrice - transaction.openPrice;
                    }
                    else if (trailingProfit - (closePrice - transaction.openPrice) > trailingParameter)
                    {
                        trailingStop = true;
                    }
                }
                else if (position1 < 0 && position2 > 0) //空头
                {
                    if (closePrice < -trailingProfit + transaction.openPrice)
                    {
                        trailingProfit = -closePrice + transaction.openPrice;
                    }
                    else if (trailingProfit - (-closePrice + transaction.openPrice) > trailingParameter)
                    {
                        trailingStop = true;
                    }
                }
                nv               = cash + position1 * underlying1ClosePrice + position2 * underlying2ClosePrice;
                nvToday          = new netvalueDaily();
                nvToday.netvalue = nv;
                nvToday.date     = today;
                netvalueList.Add(nvToday);
            }
            return(true);
        }
        private bool dualTrust(stockInfo stock, Dictionary <DateTime, parameterPair> parameters, ref List <netvalueDaily> nv, ref List <OneByOneTransaction> transactionData)
        {
            if (allStocks.ContainsKey(stock.code) == false)
            {
                return(false);
            }
            var    data        = allStocks[stock.code];
            double cash        = 10000;
            double position    = 0;
            var    myTradeDays = dateRepo.GetStockTransactionDate(stock.startDate, stock.endDate);
            OneByOneTransaction transaction = new OneByOneTransaction();
            //观察期限30分钟
            int duration = 30;
            int minutes  = 240;

            foreach (var date in myTradeDays)
            {
                if (data.ContainsKey(date) == false || parameters.ContainsKey(date) == false)
                {
                    return(false);
                }
                var    stockToday = data[date];
                var    para       = parameters[date];
                double k1         = para.parameter1;
                double k2         = para.parameter2;
                double trailing   = para.parameter3;
                double maxProfit  = 0;
                bool   tradable   = true;
                if (para.existGoodParameter == false)
                {
                    tradable = false;
                }
                //通过每日前30分钟计算指标
                double HH         = 0;     //最高价的最高价
                double HC         = 0;     //收盘价的最高价
                double LC         = 99999; //收盘价的最低价
                double LL         = 99999; //最低价的最低价
                double Range      = 0;
                double longPoint  = -1;
                double shortPoint = -1;
                for (int j = 0; j < duration; j++)
                {
                    var dataNow = stockToday[j];
                    if (dataNow.High > HH)
                    {
                        HH = dataNow.High;
                    }
                    if (dataNow.Close > HC)
                    {
                        HC = dataNow.Close;
                    }
                    if (dataNow.Close < LC)
                    {
                        LC = dataNow.Close;
                    }
                    if (dataNow.Low < LL)
                    {
                        LL = dataNow.Low;
                    }
                }
                Range      = Math.Max(HH - LC, HC - LL);
                longPoint  = stockToday[duration].Open + k1 * Range;
                shortPoint = stockToday[duration].Open - k2 * Range;
                for (int j = duration; j < minutes; j++)
                {
                    var    dataNow  = stockToday[j];
                    var    dataLast = stockToday[j - 1];
                    double avgPrice = dataNow.Close;
                    if (dataNow.Volume == 0)
                    {
                        tradable = false;
                    }
                    else
                    {
                        avgPrice = dataNow.Amount / dataNow.Volume / multiple;
                        if (para.existGoodParameter == true)
                        {
                            tradable = true;
                        }
                    }
                    if (position == 0 && j <= minutes - 10 && tradable)
                    {
                        //多头信号
                        if (dataNow.Open > longPoint && dataLast.Open < longPoint)
                        {
                            position              = 0.9 * Math.Floor(cash * 1000 / avgPrice) / 1000;
                            cash                  = cash - avgPrice * position - avgPrice * position * slipRatio;
                            transaction           = new OneByOneTransaction();
                            transaction.position  = position;
                            transaction.openTime  = dataNow.DateTime;
                            transaction.openPrice = avgPrice;
                            maxProfit             = 0;
                        }
                        //空头信号
                        else if (dataNow.Open < shortPoint && dataLast.Open > shortPoint)
                        {
                            position              = -0.9 * Math.Floor(cash * 1000 / avgPrice) / 1000;
                            cash                  = cash - avgPrice * position + avgPrice * position * slipRatio;
                            transaction           = new OneByOneTransaction();
                            transaction.position  = position;
                            transaction.openTime  = dataNow.DateTime;
                            transaction.openPrice = avgPrice;
                            maxProfit             = 0;
                        }
                    }
                    else if (position != 0 && j <= minutes - 5 && tradable) //非收盘前5分钟,按追踪止损平仓
                    {
                        if (position > 0)
                        {
                            if ((dataNow.Open / transaction.openPrice - 1) < maxProfit - trailing)
                            {
                                cash     = cash + avgPrice * position - avgPrice * position * slipRatio;
                                position = 0;
                                transaction.closePrice  = avgPrice;
                                transaction.closeTime   = dataNow.DateTime;
                                transaction.closeStatus = "追踪止损";
                                transactionData.Add(transaction);
                                transaction = new OneByOneTransaction();
                            }
                        }
                        if (position < 0)
                        {
                            if ((transaction.openPrice / dataNow.Open - 1) < maxProfit - trailing)
                            {
                                cash     = cash + avgPrice * position + avgPrice * position * slipRatio;
                                position = 0;
                                transaction.closePrice  = avgPrice;
                                transaction.closeTime   = dataNow.DateTime;
                                transaction.closeStatus = "追踪止损";
                                transactionData.Add(transaction);
                                transaction = new OneByOneTransaction();
                            }
                        }
                    }
                    else if (position != 0 && j > minutes - 5 && tradable)//收盘前5分钟强制平仓
                    {
                        if (position > 0)
                        {
                            cash     = cash + avgPrice * position - avgPrice * position * slipRatio;
                            position = 0;
                            transaction.closePrice  = avgPrice;
                            transaction.closeTime   = dataNow.DateTime;
                            transaction.closeStatus = "收盘强平";
                            transactionData.Add(transaction);
                            transaction = new OneByOneTransaction();
                        }
                        if (position < 0)
                        {
                            cash     = cash + avgPrice * position + avgPrice * position * slipRatio;
                            position = 0;
                            transaction.closePrice  = avgPrice;
                            transaction.closeTime   = dataNow.DateTime;
                            transaction.closeStatus = "收盘强平";
                            transactionData.Add(transaction);
                            transaction = new OneByOneTransaction();
                        }
                    }

                    //计算追踪止损的参数
                    if (position > 0)
                    {
                        if ((dataNow.Close / transaction.openPrice - 1) > maxProfit)
                        {
                            maxProfit = (dataNow.Close / transaction.openPrice - 1);
                        }
                    }
                    if (position < 0)
                    {
                        if ((transaction.openPrice / dataNow.Close - 1) > maxProfit)
                        {
                            maxProfit = (transaction.openPrice / dataNow.Close - 1);
                        }
                    }
                    if (j == minutes - 1)
                    {
                        dataNow = stockToday[j];
                        netvalueDaily nvToday = new netvalueDaily();
                        nvToday.date     = dataNow.DateTime.Date;
                        nvToday.netvalue = cash + position * dataNow.Close;
                        nv.Add(nvToday);
                    }
                }
            }
            return(true);
        }
        private List <OneByOneTransaction> computeDailyWithRecordByTick(DateTime date, string bond, string stock, double stopLossRatio)
        {
            List <OneByOneTransaction> record = new List <OneByOneTransaction>();

            if (tickData.ContainsKey(date) == false || tickData[date].ContainsKey(bond) == false || tickData[date].ContainsKey(stock) == false)
            {
                return(record);
            }

            double ceilPrice         = getCeilingPrice(date, stock);
            double previousAmount    = getPreviousAmount(date, stock);
            double previousBondPrice = getPreviousBondClose(date, bond);
            var    bondData          = tickData[date][bond];
            var    stockData         = tickData[date][stock];
            var    bondDailyInfoNow  = getBondDailyInfo(date, bond);
            double strike            = bondDailyInfoNow.conversionPrice;
            double numbers           = 100 / strike;
            double delta             = getOptionDelta(date, bond, stock);

            delta = delta + 0.2;
            double bondEstimatePrice = getEstimateBondPrice(date, bond, stock);

            if (bondEstimatePrice < previousBondPrice)
            {
                previousBondPrice = bondEstimatePrice;
            }
            //if (ceilPrice<strike)
            //{
            //    delta = 0.5;
            //}
            //else if (ceilPrice<1.5*strike)
            //{
            //    delta = 0.8;
            //}
            //else
            //{
            //    delta = 1;
            //}
            double stockPriceChanged = ceilPrice / 11;
            //ceilPrice = stockData[0].HighLimit;
            var      allData        = getMergeData(bondData, stockData);
            double   position       = 0;
            double   openPrice      = 0;
            DateTime openTime       = new DateTime();
            DateTime closeTime      = new DateTime();
            double   closePrice     = 0;
            double   maxOpenAmount  = 0;
            double   maxCloseAmount = 0;
            double   longMaxPrice   = 0;
            string   status         = "";
            TimeSpan lastOpenTime   = new TimeSpan(14, 55, 00);
            TimeSpan firstOpenTime  = new TimeSpan(9, 30, 00);
            var      recordNow      = new OneByOneTransaction();
            int      index          = 0;

            while (index < allData.Count() - 1)
            {
                //正股涨停
                if (allData[index].Code == stock && allData[index].AskV1 == 0 && allData[index].Bid1 == ceilPrice && allData[index + 1].Code == bond && allData[index + 1].AskV1 > 0 && position == 0 && allData[index].TransactionDateTime.TimeOfDay < lastOpenTime && allData[index].TransactionDateTime.TimeOfDay >= firstOpenTime)
                {
                    double ceilAmount = allData[index].Bid1 * allData[index].BidV1;
                    if (ceilAmount > previousAmount * 0.2 && allData[index + 1].LastPrice < previousBondPrice + delta * numbers * stockPriceChanged)
                    {
                        recordNow = new OneByOneTransaction();
                        var bondDataNow = allData[index + 1];
                        maxOpenAmount = bondDataNow.Ask1 * bondDataNow.AskV1;
                        double bondVolume = bondDataNow.AskV1;
                        if (maxOpenAmount >= 10000 && (maxOpenAmount / bondVolume) < 1000)
                        {
                            position                = 1;
                            openPrice               = maxOpenAmount / bondVolume;
                            openTime                = bondDataNow.TransactionDateTime;
                            recordNow.code          = bond;
                            recordNow.maxOpenAmount = maxOpenAmount;
                            recordNow.openPrice     = openPrice;
                            recordNow.openTime      = openTime;
                            recordNow.date          = date.Date;
                        }
                        index++;
                    }
                }
                //涨停打开或者将要打开卖出可转债
                if (position == 1 && allData[index].Code == stock && (allData[index].Bid1 < ceilPrice || (allData[index].Bid1 == ceilPrice && allData[index].Bid1 * allData[index].BidV1 < previousAmount * 0.03)))
                {
                    for (int i = 1; i < allData.Count() - index; i++)
                    {
                        if (allData[index + i].Code == bond)//找到bond对应的数据
                        {
                            position = 0;
                            var bondDataNow = allData[index + i];
                            maxCloseAmount = bondDataNow.Bid1 * bondDataNow.BidV1;
                            double bondVolume = bondDataNow.BidV1;
                            closePrice = maxCloseAmount / bondVolume;
                            if (bondVolume == 0)
                            {
                                closePrice = bondDataNow.LastPrice;
                            }
                            closeTime = bondDataNow.TransactionDateTime;
                            recordNow.maxCloseAmount = maxCloseAmount;
                            recordNow.closePrice     = closePrice;
                            recordNow.closeTime      = closeTime;
                            recordNow.closeStatus    = "涨停即将打开或已经打开";
                            recordNow.yield          = (recordNow.closePrice - recordNow.openPrice) / recordNow.openPrice;
                            record.Add(recordNow);
                            index = index + i;
                            break;
                        }
                    }
                }

                //正股封涨停但是可转债跌幅过大,止损卖出
                if (position == 1 && allData[index].Code == bond && allData[index].LastPrice < (1 - stopLossRatio) * openPrice)
                {
                    position = 0;
                    var bondDataNow = allData[index];
                    maxCloseAmount = bondDataNow.Bid1 * bondDataNow.BidV1;
                    double bondVolume = bondDataNow.BidV1;
                    closePrice = maxCloseAmount / bondVolume;
                    if (bondVolume == 0)
                    {
                        closePrice = bondDataNow.LastPrice;
                    }
                    closeTime = bondDataNow.TransactionDateTime;
                    recordNow.maxCloseAmount = maxCloseAmount;
                    recordNow.closePrice     = closePrice;
                    recordNow.closeTime      = closeTime;
                    recordNow.closeStatus    = "涨停未打开但可转债下跌";
                    recordNow.yield          = (recordNow.closePrice - recordNow.openPrice) / recordNow.openPrice;
                    record.Add(recordNow);
                    index = index++;
                }

                //14点57分之后,强制平仓
                if (position == 1 && allData[index].TransactionDateTime.TimeOfDay >= lastOpenTime)
                {
                    for (int i = 1; i < allData.Count() - index; i++)
                    {
                        if (allData[index + i].Code == bond)//找到bond对应的数据
                        {
                            position = 0;
                            var bondDataNow = allData[index + i];
                            maxCloseAmount = bondDataNow.Bid1 * bondDataNow.BidV1;
                            double bondVolume = bondDataNow.BidV1;
                            closePrice = maxCloseAmount / bondVolume;
                            if (bondVolume == 0)
                            {
                                closePrice = bondDataNow.LastPrice;
                            }
                            closeTime = bondDataNow.TransactionDateTime;
                            recordNow.maxCloseAmount = maxCloseAmount;
                            recordNow.closePrice     = closePrice;
                            recordNow.closeTime      = closeTime;
                            recordNow.closeStatus    = "收盘强平";
                            recordNow.yield          = (recordNow.closePrice - recordNow.openPrice) / recordNow.openPrice;
                            record.Add(recordNow);
                            index = index + i;
                            break;
                        }
                    }
                }
                index++;
            }
            return(record);
        }
        private OneByOneTransaction computeDailyWithRecordByMinute(DateTime date, string bond, string stock, double stopLossRatio)
        {
            OneByOneTransaction record = new OneByOneTransaction();

            if (minuteData.ContainsKey(date) == false || minuteData[date].ContainsKey(bond) == false || minuteData[date].ContainsKey(stock) == false)
            {
                return(record);
            }
            double   ceilPrice      = getCeilingPrice(date, stock);
            var      bondData       = minuteData[date][bond];
            var      stockData      = minuteData[date][stock];
            double   position       = 0;
            double   openPrice      = 0;
            DateTime openTime       = new DateTime();
            DateTime closeTime      = new DateTime();
            double   closePrice     = 0;
            double   maxOpenAmount  = 0;
            double   maxCloseAmount = 0;
            double   longMaxPrice   = 0;
            string   status         = "";

            for (int i = 0; i < stockData.Count() - 5; i++)
            {
                if (stockData[i].High == ceilPrice && position == 0 && bondData[i + 1].Volume > 0)
                {
                    position      = 1;
                    openPrice     = bondData[i + 1].Amount / bondData[i + 1].Volume;
                    maxOpenAmount = bondData[i + 1].Amount;
                    openTime      = stockData[i + 1].DateTime;
                    longMaxPrice  = openPrice;
                }
                if (position == 1 && (bondData[i].Close - longMaxPrice) / longMaxPrice < -stopLossRatio && stockData[i].Close < ceilPrice * 0.995)
                {
                    position = 0;
                    if (bondData[i + 1].Volume > 0)
                    {
                        closePrice = bondData[i + 1].Amount / bondData[i + 1].Volume;
                    }
                    else
                    {
                        closePrice = bondData[i + 1].Close;
                    }
                    maxCloseAmount = bondData[i + 1].Amount;
                    closeTime      = bondData[i + 1].DateTime;
                    status         = "追踪止损";
                    break;
                }
                else if (position == 1 && bondData[i].Close > longMaxPrice)
                {
                    longMaxPrice = bondData[i].Close;
                }
            }
            //收盘之前3分钟平仓
            if (position == 1)
            {
                position = 0;
                if (bondData[stockData.Count() - 3].Volume > 0)
                {
                    closePrice = bondData[stockData.Count() - 3].Amount / bondData[stockData.Count() - 3].Volume;
                }
                else
                {
                    closePrice = bondData[stockData.Count() - 3].Close;
                }
                maxCloseAmount = bondData[stockData.Count() - 3].Amount;
                closeTime      = bondData[stockData.Count() - 3].DateTime;
                status         = "收盘强平";
            }

            record.openPrice      = openPrice;
            record.openTime       = openTime;
            record.closePrice     = closePrice;
            record.closeTime      = closeTime;
            record.maxOpenAmount  = maxOpenAmount;
            record.maxCloseAmount = maxCloseAmount;
            record.position       = position;
            record.yield          = (closePrice - openPrice) / openPrice;
            record.date           = date.Date;
            record.closeStatus    = status;
            record.code           = bond;
            return(record);
        }
        //按照给定参数回测
        private OneByOneTransaction computeDailyWithRecord(DateTime date, int N, double K1, double K2, double lossStopRatio)
        {
            OneByOneTransaction result = new OneByOneTransaction();

            return(result);
        }
Esempio n. 8
0
        //按照给定参数回测
        private OneByOneTransaction computeDailyWithRecord(DateTime date, int N, double K1, double K2, double lossStopRatio)
        {
            OneByOneTransaction result = new OneByOneTransaction();

            if ((volDic.ContainsKey(N) && volDic[N].ContainsKey(date) && underlyingKLine.ContainsKey(date)) == false)
            {
                return(result);
            }
            result.date = date;
            double yield      = 0;
            double vol        = volDic[N][date];
            var    underlying = underlyingKLine[date];

            double position      = 0;
            double positionflag  = 0;
            double openPrice     = 0;
            double closePrice    = 0;
            double longMaxPrice  = 0;
            double shortMinPrice = 99999;
            double open          = underlying[N].Open;
            double range         = open * vol;

            result.parameter = vol;
            double lossStopPoints = lossStopRatio * open;
            double slipBuy        = 0;
            double slipSell       = 0;

            for (int i = 1; i < 60; i++)
            {
                if (vol < 0.005)
                {
                    continue;
                }
                slipBuy  = Math.Max(slipRatio * underlying[i].Open, priceUnit) + feeRatioBuy * underlying[i].Open;
                slipSell = Math.Max(slipRatio * underlying[i].Open, priceUnit) + feeRatioSell * underlying[i].Open;
                if (position == 0 && underlying[i].Open > open + K1 * range && underlying[i].Amount > 0)
                {
                    openPrice        = underlying[i].Open + slipBuy;
                    longMaxPrice     = openPrice;
                    positionflag     = 1;
                    position         = 1;
                    result.openTime  = underlying[i].DateTime;
                    result.openPrice = openPrice;
                    result.position  = 1;
                }
                if (position == 0 && underlying[i].Open < open - K2 * range && underlying[i].Amount > 0)
                {
                    openPrice        = underlying[i].Open - slipSell;
                    shortMinPrice    = openPrice;
                    positionflag     = -1;
                    position         = -1;
                    result.openTime  = underlying[i].DateTime;
                    result.openPrice = openPrice;
                    result.position  = -1;
                }
                if (position == 1 && underlying[i].Open > longMaxPrice && underlying[i].Amount > 0)
                {
                    longMaxPrice = underlying[i].Open;
                }
                if (position == -1 && underlying[i].Open < shortMinPrice && underlying[i].Amount > 0)
                {
                    shortMinPrice = underlying[i].Open;
                }
                if (position == 1 && underlying[i].Open < longMaxPrice - lossStopPoints && underlying[i].Amount > 0)
                {
                    closePrice         = underlying[i].Open - slipSell;
                    position           = 0;
                    result.closeTime   = underlying[i].DateTime;
                    result.closePrice  = closePrice;
                    result.closeStatus = "追踪止损";
                    break;
                }
                if (position == -1 && underlying[i].Open > shortMinPrice + lossStopPoints && underlying[i].Amount > 0)
                {
                    closePrice         = underlying[i].Open + slipBuy;
                    position           = 0;
                    result.closeTime   = underlying[i].DateTime;
                    result.closePrice  = closePrice;
                    result.closeStatus = "追踪止损";
                    break;
                }
            }
            if (position != 0)
            {
                slipBuy  = Math.Max(slipRatio * underlying[underlying.Count() - 3].Open, priceUnit) + feeRatioBuy * underlying[underlying.Count() - 3].Open;
                slipSell = Math.Max(slipRatio * underlying[underlying.Count() - 3].Open, priceUnit) + feeRatioSell * underlying[underlying.Count() - 3].Open;
                if (position == 1)
                {
                    closePrice         = underlying[underlying.Count() - 3].Open - slipSell;
                    position           = 0;
                    result.closeTime   = underlying[underlying.Count() - 3].DateTime;
                    result.closePrice  = closePrice;
                    result.closeStatus = "收盘强平";
                }
                else if (position == -1)
                {
                    closePrice         = underlying[underlying.Count() - 3].Open + slipBuy;
                    position           = 0;
                    result.closeTime   = underlying[underlying.Count() - 3].DateTime;
                    result.closePrice  = closePrice;
                    result.closeStatus = "收盘强平";
                }
            }
            if (positionflag != 0)
            {
                yield = (closePrice / openPrice - 1) * positionflag;
            }
            result.yield = yield;
            return(result);
        }