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); }
//按照给定参数回测 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); }