public override TradeRecords DoBuy(TimeSerialsDataSet ds, Properties strategyParam, BacktestParameter backtestParam) { TimeSeries <ITimeSeriesItem <List <double> > > dayFunds = ds.FundTrendCreateOrLoad(TimeUnit.day); TimeSeries <ITimeSeriesItem <List <double> > > weekFunds = ds.FundTrendCreateOrLoad(TimeUnit.week); TimeSeries <ITimeSeriesItem <double> > dayCross = ds.FundTrendCrossCreateOrLoad(TimeUnit.day); TimeSeries <ITimeSeriesItem <double> > weekCross = ds.FundTrendCrossCreateOrLoad(TimeUnit.day); if (dayFunds == null || dayFunds.Count <= 0 || weekFunds == null || weekFunds.Count <= 0 || dayCross == null || dayCross.Count <= 0 || weekCross == null || weekCross.Count <= 0) { return(null); } TradeRecords tr = new TradeRecords(ds.Code); DateTime begin = backtestParam.BeginDate; DateTime end = backtestParam.EndDate; double p_day_low = strategyParam.Get <double>("day_low"); double p_day_bias = strategyParam.Get <double>("day_bias"); double p_week_low = strategyParam.Get <double>("week_low"); double p_week_bias = strategyParam.Get <double>("week_bias"); GetInMode p_getinMode = (GetInMode)strategyParam.Get <Object>("getinMode"); for (int i = 0; i < dayFunds.Count; i++) { ITimeSeriesItem <List <double> > dayFundItem = dayFunds[i]; if (dayFundItem == null) { continue; } if (dayFundItem.Date < begin || dayFundItem.Date >= end) { continue; } if ((dayFundItem.Value[0] - dayFundItem.Value[1]) < p_day_bias) { continue; } DateTime td = CalendarUtils.GetWeek(dayFundItem.Date, DayOfWeek.Friday); ITimeSeriesItem <List <double> > weekFundItem = weekFunds[td]; if (weekFundItem == null) { continue; } if ((weekFundItem.Value[0] - weekFundItem.Value[1]) < p_week_bias) { continue; } KLine dayLine = ds.DayKLine; if (dayLine == null) { continue; } KLineItem dayLineItem = dayLine[dayFundItem.Date]; if (dayLineItem == null) { continue; } TradeBout bout = new TradeBout(ds.Code); bout.RecordTrade(1, dayFundItem.Date, TradeDirection.Buy, dayLineItem.CLOSE, (int)(p_getinMode.Value / dayLineItem.CLOSE), 0, 0, Name); tr.Bouts.Add(bout); } return(tr); }
public void Execute() { List <String> codes = new List <string>(); System.IO.File.ReadAllLines(FileUtils.GetDirectory() + "test.csv") .ToList().ForEach(x => codes.Add(x.Split(',')[1])); IndicatorRepository repository = new IndicatorRepository("d:\\repository\\"); repository.Initilization(); foreach (String code in codes) { //生成数据 TimeSerialsDataSet ds = repository[code]; KLine dayLine = ds.DayKLine; KLine weekLine = dayLine.CreateWeek(); ds.WeekKLine = weekLine; TimeSeries <ITimeSeriesItem <double> > dayClose = dayLine.Select <double>("close", 0, 0); TimeSeries <ITimeSeriesItem <double> > weekClose = weekLine.Select <double>("close", 0, 0); TradingLine dayTradeLine = ds.CubeCreateOrLoad(TimeUnit.day); TradingLine weekTradeLine = ds.CubeCreateOrLoad(TimeUnit.week); TimeSeries <ITimeSeriesItem <List <double> > > dayFunds = ds.FundTrendCreate(TimeUnit.day); TimeSeries <ITimeSeriesItem <List <double> > > weekFunds = ds.FundTrendCreate(TimeUnit.week); TimeSeries <ITimeSeriesItem <double> > dayCross = ds.FundTrendCrossCreateOrLoad(TimeUnit.day); TimeSeries <ITimeSeriesItem <double> > weedCross = ds.FundTrendCrossCreateOrLoad(TimeUnit.week); //测试买入 List <TradeBout> bouts = new List <TradeBout>(); TimeSeries <ITimeSeriesItem <char> > dayTradePt = dayTradeLine.buysellPoints; for (int i = 0; i < dayTradePt.Count; i++) { ITimeSeriesItem <char> item = dayTradePt[i]; if (item.Value == 'S') { continue; } if (item.Date < begin || item.Date > end) { continue; } DateTime buyPtDate = item.Date; int index = dayFunds.IndexOf(buyPtDate); while (index <= dayFunds.Count) { ITimeSeriesItem <List <double> > fundItem = dayFunds[index]; if (fundItem == null) { index += 1; continue; } if (fundItem.Value[0] <= fundItem.Value[1]) { index += 1; continue; } TradeBout bout = new TradeBout(code); KLineItem klineItem = dayLine.GetNearest(fundItem.Date, false); if (klineItem == null) { index += 1; continue; } bout.RecordTrade(1, klineItem.Date, TradeDirection.Buy, klineItem.CLOSE, (int)(funds / klineItem.CLOSE), 0, 0, "发出B点且主力=" + fundItem.Value[0].ToString("F3") + "大于散户" + fundItem.Value[1].ToString("F3") + ",日期=" + fundItem.Date.ToString("yyyyMMdd")); bouts.Add(bout); break; } } //测试卖出 for (int i = 0; i < bouts.Count; i++) { DateTime buyDate = bouts[i].BuyInfo.TradeDate; int buyIndex = dayLine.IndexOf(buyDate); int index = buyIndex + 1; while (index <= dayLine.Count - 1) { KLineItem item = dayLine[index]; if (index - buyIndex >= maxdays) { bouts[i].RecordTrade(2, item.Date, TradeDirection.Sell, item.CLOSE, bouts[i].BuyInfo.Amount, 0, 0, "大于" + maxdays.ToString() + "天卖出"); break; } else { double profile = (item.HIGH - bouts[i].BuyInfo.TradePrice) / bouts[i].BuyInfo.TradePrice; if (profile >= maxProfilt) { bouts[i].RecordTrade(2, item.Date, TradeDirection.Sell, (bouts[i].BuyInfo.TradePrice * (1 + maxProfilt)), bouts[i].BuyInfo.Amount, 0, 0, "利润大于" + maxdays.ToString() + "天卖出"); break; } } index += 1; } } //去掉未完成的 for (int i = 0; i < bouts.Count; i++) { if (!bouts[i].Completed) { bouts.RemoveAt(i--); } } TradeRecords tradeRecords = new TradeRecords(); tradeRecords.Bouts.AddRange(bouts); //打印结果 for (int i = 0; i < bouts.Count; i++) { Console.WriteLine(bouts[i].ToString()); } Console.WriteLine(tradeRecords.ToString()); } }
public override bool DoSell(string code, TradeBout bout, DateTime d, Properties strategyParam, BacktestParameter backtestParam, out string reason) { reason = ""; if (bout == null) { return(false); } IndicatorRepository repository = (IndicatorRepository)backtestParam.Get <Object>("repository"); if (repository == null) { return(false); } TimeSerialsDataSet ds = repository[bout.Code]; if (ds == null) { return(false); } KLine kline = ds.DayKLine; if (kline == null) { return(false); } //跳过已完成的 if (bout.Completed) { return(false); } TimeSeries <ITimeSeriesItem <char> > btpoints = ds.DayTradeLine.buysellPoints; if (btpoints == null || btpoints.Count <= 0) { return(false); } ITimeSeriesItem <char> item = btpoints[d]; if (item == null || item.Value == 'B') { return(false); } KLineItem klineItemDay = kline[d]; if (klineItemDay == null) { return(false); } double price = klineItemDay.CLOSE; //if (price < bout.BuyInfo.TradePrice) // return true; int amount = bout.BuyInfo.Amount; bout.RecordTrade(2, klineItemDay.Date, TradeDirection.Sell, price, amount, backtestParam.Volumecommission, backtestParam.Stampduty, "日线出S点"); return(false); }
public override TradeRecords Execute(string code, Properties strategyParam, BacktestParameter backtestParam, ISeller seller = null) { IndicatorRepository repository = (IndicatorRepository)backtestParam.Get <Object>("repository"); //取得策略参数 double buy_mainlow = strategyParam.Get <double>("buy_mainlow"); //主力线低位买入 int buy_cross = strategyParam.Get <int>("buy_cross"); GetInMode p_getinMode = (GetInMode)strategyParam.Get <GetInMode>("getinMode"); TradeRecords tr = new TradeRecords(code); TimeSerialsDataSet ds = repository[code]; if (ds == null) { return(null); } KLine kline = ds.DayKLine; if (kline == null) { return(null); } TimeSeries <ITimeSeriesItem <List <double> > > dayFunds = ds.DayFundTrend; TimeSeries <ITimeSeriesItem <double> > dayFundsCross = ds.DayFundTrendCross; if (buy_cross == 0 && dayFunds == null) { return(null); } else if (buy_cross == 1 && (dayFundsCross == null || dayFunds == null)) { return(null); } #region 判断主力线低位决定买入点 if (buy_cross == 0) { for (int i = 0; i < dayFunds.Count; i++) { if (dayFunds[i].Date.Date <backtestParam.BeginDate || dayFunds[i].Date.Date> backtestParam.EndDate) { continue; } if (double.IsNaN(dayFunds[i].Value[0])) { continue; } if (dayFunds[i].Value[0] > buy_mainlow) { continue; } //主力线开始低于buy_mainlow... i += 1; while (i < dayFunds.Count) { if (dayFunds[i].Value[0] <= buy_mainlow) { i += 1; continue; } //主力线出了buy_mainlow KLineItem klineItem = kline[dayFunds[i].Date]; if (klineItem == null) { break; } int tIndex = kline.IndexOf(klineItem); if (tIndex >= kline.Count - 1) { break; } KLineItem klineItemNext = kline[tIndex + 1]; TradeBout bout = new TradeBout(code); double price = klineItem.CLOSE; if (price > klineItemNext.HIGH || price < klineItemNext.LOW) { break; } bout.RecordTrade(1, dayFunds[i].Date.Date, TradeDirection.Buy, price, (int)(p_getinMode.Value / price), backtestParam.Volumecommission, backtestParam.Stampduty, "主力线低于" + buy_mainlow.ToString("F2")); tr.Bouts.Add(bout); break; } } } #endregion #region 判断金叉决定买入点 else if (buy_cross == 1) { for (int i = 0; i < dayFundsCross.Count; i++) { if (dayFundsCross[i].Date.Date <backtestParam.BeginDate || dayFundsCross[i].Date.Date> backtestParam.EndDate) { continue; } if (dayFundsCross[i].Value <= 0) { continue; } ITimeSeriesItem <List <double> > dayFundItem = dayFunds[dayFundsCross[i].Date]; if (dayFundItem == null) { continue; } if (buy_mainlow != 0 && dayFundItem.Value[0] >= buy_mainlow) { continue; } KLineItem klineItem = kline[dayFundItem.Date]; if (klineItem == null) { continue; } int tIndex = kline.IndexOf(klineItem); if (tIndex >= kline.Count - 1) { continue; } KLineItem klineItemNext = kline[tIndex + 1]; TradeBout bout = new TradeBout(code); double price = klineItem.CLOSE; if (price > klineItemNext.HIGH || price < klineItemNext.LOW) { continue; } bout.RecordTrade(1, dayFunds[i].Date.Date, TradeDirection.Buy, price, (int)(p_getinMode.Value / price), backtestParam.Volumecommission, backtestParam.Stampduty, "主力线低于" + buy_mainlow.ToString("F2")); tr.Bouts.Add(bout); } } #endregion return(tr); }
public override TradeRecords Execute(String code, Properties strategyParam, BacktestParameter backtestParam, ISeller seller = null) { IndicatorRepository repository = (IndicatorRepository)backtestParam.Get <Object>("repository"); if (repository == null) { return(null); } //取得策略参数 double buy_mainlow = strategyParam.Get <double>("buy_mainlow"); //主力线低位买入 int buy_cross = strategyParam.Get <int>("buy_cross"); GetInMode p_getinMode = (GetInMode)strategyParam.Get <GetInMode>("getinMode"); //取得行情数据 TradeRecords tr = new TradeRecords(code); TimeSerialsDataSet ds = repository[code]; if (ds == null) { return(null); } KLine kline = ds.DayKLine; if (kline == null) { return(null); } MACD macd = (MACD)ds.Create("macd", TimeUnit.day, false); if (macd == null) { return(null); } //买入条件判定 for (int i = 0; i < macd.Count; i++) { MACDItem macdItem = macd[i]; if (macdItem.Date < backtestParam.BeginDate || macdItem.Date >= backtestParam.EndDate) { continue; } if (macdItem.CROSS <= 0) { continue; } if (macdItem.DIF > buy_mainlow) { continue; } DateTime d = macdItem.Date; KLineItem klineItem = kline[d]; if (klineItem == null) { continue; } TradeBout bout = new TradeBout(code); bout.RecordTrade(1, d, TradeDirection.Buy, klineItem.CLOSE, (int)(p_getinMode.Value / klineItem.CLOSE), backtestParam.Volumecommission, backtestParam.Stampduty, "低位金叉" + macdItem.DIF.ToString("F2")); tr.Bouts.Add(bout); } return(tr); }
/// <summary> /// 执行卖出操作 /// </summary> /// <param name="tradeRecord"></param> /// <param name="strategyParam"></param> /// <param name="backtestParam"></param> public override void Execute(TradeRecords tradeRecord, Properties strategyParam, BacktestParameter backtestParam) { //初始化行情库 if (tradeRecord == null) { return; } IndicatorRepository repository = (IndicatorRepository)backtestParam.Get <Object>("repository"); if (repository == null) { return; } //取得策略参数 int p_maxday = strategyParam.Get <int>("maxholddays"); //遍历每一个买入回合 String code = tradeRecord.Code; List <TradeBout> bouts = tradeRecord.Bouts; for (int i = 0; i < bouts.Count; i++) { TradeBout bout = bouts[i]; TimeSerialsDataSet ds = repository[bout.Code]; if (ds == null) { continue; } if (bout.Completed) { continue; //跳过已完成的 } KLine kline = ds.DayKLine; if (kline == null) { continue; } int bIndex = kline.IndexOf(bout.BuyInfo.TradeDate); //寻找p_maxday天内最大收益那天 KLineItem maxProfileItem = null; for (int index = bIndex + 1; index <= bIndex + 1 + p_maxday; index++) { if (index >= kline.Count) { break; } KLineItem item = kline[index]; if (item.CLOSE > (maxProfileItem == null?0: maxProfileItem.CLOSE)) { maxProfileItem = item; } } if (maxProfileItem == null) { continue; } bout.RecordTrade(2, maxProfileItem.Date, TradeDirection.Sell, maxProfileItem.CLOSE, bout.BuyInfo.Amount, backtestParam.Volumecommission, backtestParam.Stampduty, ""); } }
public override TradeRecords Execute(string code, Properties strategyParam, BacktestParameter backtestParam, ISeller seller = null) { IndicatorRepository repository = (IndicatorRepository)backtestParam.Get <Object>("repository"); if (repository == null) { return(null); } TimeSerialsDataSet ds = repository[code]; if (ds == null) { return(null); } TimeSeries <ITimeSeriesItem <char> > ts = ds.DayTradeLine.buysellPoints; if (ts == null) { return(null); } TimeSeries <ITimeSeriesItem <List <double> > > fundTrends = ds.DayFundTrend; KLine kline = ds.DayKLine; TradeRecords tr = new TradeRecords(code); GetInMode getin = GetInMode.Parse(strategyParam.Get <String>("getinMode")); int diffdays = strategyParam.Get <int>("diffdays"); for (int i = 0; i < ts.Count; i++) { if (ts[i].Date.Date < backtestParam.BeginDate) { continue; } if (ts[i].Date.Date >= backtestParam.EndDate) { continue; } if (ts[i].Value == 'S') { continue; } TradeBout bout = new TradeBout(code); //主力线大于散户线,且连续diffdays天与散户线拉大距离 if (diffdays > 0 && fundTrends != null) { int fi = fundTrends.IndexOf(ts[i].Date); if (fi < 0 || fi < diffdays - 1) { continue; } ITimeSeriesItem <List <double> > ftItem = fundTrends[fi]; if (ftItem.Value[0] >= 30) { continue; } double diff = ftItem.Value[0] - ftItem.Value[1]; if (diff <= 0) { continue; } bool continuekuoda = true; for (int t = 1; t < diffdays; t++) { ftItem = fundTrends[fi - i]; double tDiff = ftItem.Value[0] - ftItem.Value[1]; if (diff < tDiff) { continuekuoda = false; break; } diff = tDiff; } if (!continuekuoda) { continue; } } KLineItem item = kline[ts[i].Date]; bout.RecordTrade(1, ts[i].Date, TradeDirection.Buy, item.CLOSE, (int)(getin.Value / item.CLOSE), backtestParam.Volumecommission, backtestParam.Stampduty, "B"); tr.Bouts.Add(bout); } return(tr); }
public override bool DoSell(String code, TradeBout bout, DateTime d, Properties strategyParam, BacktestParameter backtestParam, out String reason) { reason = ""; if (bout == null) { return(false); } IndicatorRepository repository = (IndicatorRepository)backtestParam.Get <Object>("repository"); if (repository == null) { return(false); } TimeSerialsDataSet ds = repository[bout.Code]; if (ds == null) { return(false); } KLine kline = ds.DayKLine; if (kline == null) { return(false); } //跳过已完成的 if (bout.Completed) { return(false); } //取得策略参数 int p_spoints = strategyParam.Get <int>("spoints"); int p_totaldropcount = strategyParam.Get <int>("totaldropcount"); int p_continuedropcount = strategyParam.Get <int>("continuedropcount"); #region 判断发出S点卖出:p_spoints=1表示日线出S点,p_spoints=2表示60分钟线出S点 if (p_spoints > 0 && ds.DayTradeLine != null && ds.DayTradeLine.buysellPoints != null && ds.DayTradeLine.buysellPoints.Count > 0) { ITimeSeriesItem <char> bsptItemDay = ds.DayTradeLine.buysellPoints[d]; if (bsptItemDay != null && bsptItemDay.Value == 'S') { KLineItem klineItemDay = kline[d]; if (klineItemDay != null) { double price = klineItemDay.CLOSE; int amount = bout.BuyInfo.Amount; bout.RecordTrade(2, klineItemDay.Date, TradeDirection.Sell, price, amount, backtestParam.Volumecommission, backtestParam.Stampduty, "日线出S点"); return(false); } } } #endregion #region 根据价格下降情况判断是否卖出 if (p_continuedropcount > 0 || p_totaldropcount > 0) { int bIndex = kline.IndexOf(bout.BuyInfo.TradeDate); int index = bIndex + 1; if (index >= kline.Count) { return(false); } KLineItem item = kline[index]; DateTime td = item.Date; int totaldropcount = 0, continuedropcount = 0; double prevPrice = bout.BuyInfo.TradePrice; bool prevDrop = item.Average < prevPrice; while (td <= d && index < kline.Count - 1) { double price = item.Average; if (price < prevPrice) { totaldropcount += 1; if (prevDrop) { continuedropcount += 1; } prevDrop = true; } else { prevDrop = false; } index += 1; item = kline[index]; td = item.Date; } //进入到伺机卖出状态 if (p_continuedropcount != 0 && continuedropcount >= p_continuedropcount) { return(true); } //进入到伺机卖出情况 if (p_totaldropcount != 0 && totaldropcount >= p_totaldropcount) { return(true); } } #endregion return(false); }
public override bool DoSell(string code, TradeBout bout, DateTime d, Properties strategyParam, BacktestParameter backtestParam, out string reason) { reason = ""; if (bout == null) { return(false); } if (bout.Completed) { return(false); } //取得策略参数 int sell_maxholddays = strategyParam.Get <int>("maxholddays"); //最大持仓天数 int sell_notrun_num = strategyParam.Get <int>("sell_notrun_num"); //主力线与价格趋势不符允许出现的最大次数 int sell_selectnum = strategyParam.Get <int>("sell_selectnum"); //可以尝试的最大卖出次数 double sell_mainvalve = strategyParam.Get <double>("sell_mainvalve"); //主力线高位阈值 double sell_mainvalve_diff = strategyParam.Get <double>("sell_mainvalve_diff"); //主力线高位增幅 double sell_slopediff = strategyParam.Get <double>("sell_slopediff"); //主力线和收盘价的斜率差阈值 sell_slopediff = (sell_slopediff / 180) * Math.PI; double sell_slopepoint = strategyParam.Get <double>("sell_slopepoint"); //线性回归斜率的卖点 sell_slopepoint = (sell_slopepoint / 180) * Math.PI; GetInMode p_getinMode = (GetInMode)strategyParam.Get <GetInMode>("getinMode"); //取得行情数据 IndicatorRepository repository = (IndicatorRepository)backtestParam.Get <Object>("repository"); if (repository == null) { return(false); } TimeSerialsDataSet ds = repository[bout.Code]; if (ds == null) { return(false); } KLine kline = ds.DayKLine; TimeSeries <ITimeSeriesItem <List <double> > > dayFunds = ds.DayFundTrend; TimeSeries <ITimeSeriesItem <double> > dayFundsCross = ds.DayFundTrendCross; DateTime curDate = d; DateTime buyDate = bout.BuyInfo.TradeDate;//买入日期 d = buyDate.AddDays(1); int days = 1; //买入后的第几天 double prevMainFundValue = 0; //前一日的主力值 double mainFunddiff = 0; //主力线当日与前一日的差值 int is_slope_run = 0; //主力线和收盘价走势是否一致,0未知;1一致;-1,-2不一致 int sellnum = 0; //择机卖出次数 int state = 0; //当日状态;0未知;1 择机卖出(在连续sell_selectnum内只要不亏损就卖) String stateReason = ""; //卖出原因 while (d <= curDate) { //查找d日的资金线,找不到则跳过这天 int dayFundIndex = dayFunds.IndexOf(d); if (dayFundIndex < 0) { d = d.AddDays(1); continue; } ITimeSeriesItem <List <double> > dayFundsItem = dayFunds[dayFundIndex]; //查找当日K线,找不到则跳过这天 int dayKLineIndex = kline.IndexOf(d); if (dayKLineIndex < 0) { d = d.AddDays(1); continue; } KLineItem dayLineItem = kline[dayKLineIndex]; //对买入后的每一天 //1.计算以d日收盘价卖出的盈利情况 bout.RecordTrade(2, d, TradeDirection.Sell, kline[dayKLineIndex].CLOSE, bout.BuyInfo.Amount, backtestParam.Volumecommission, backtestParam.Stampduty); double earnRate = bout.EarningsRate; bout.TradeInfos[1] = null; //如果是择机卖出状态 if (state == 1) { if (sellnum > sell_selectnum || earnRate > 0) { bout.RecordTrade(2, d, TradeDirection.Sell, kline[dayKLineIndex].CLOSE, bout.BuyInfo.Amount, backtestParam.Volumecommission, backtestParam.Stampduty, stateReason + ",延迟天数=" + sellnum.ToString()); break; } sellnum += 1; d = d.AddDays(1); days += 1; continue; } //如果超过最大持仓天数,则进入到择机卖出 if (days >= sell_maxholddays) { state = 1; continue; } //趋势不一致出现sell_notrun_num次,择机卖出 if (is_slope_run <= -1 * sell_notrun_num) { stateReason = "主力线趋势不符" + is_slope_run.ToString() + "次数"; state = 1; d = d.AddDays(1); days += 1; continue; } //主力线超出预定值 if (sell_mainvalve != 0 && dayFunds[dayFundIndex].Value[0] >= sell_mainvalve) { if (prevMainFundValue == 0) { prevMainFundValue = dayFunds[dayFundIndex].Value[0]; d = d.AddDays(1); days += 1; continue; } else if ((dayFunds[dayFundIndex].Value[0] - prevMainFundValue) > sell_mainvalve_diff) { d = d.AddDays(1); days += 1; continue; } mainFunddiff = (dayFunds[dayFundIndex].Value[0] - prevMainFundValue); //如果盈利率小于0,延迟数天卖出 if (earnRate <= 0) { state = 1; stateReason = "主力线突破高位且增幅减缓" + mainFunddiff.ToString("F3"); d = d.AddDays(1); days += 1; continue; } //卖出操作 bout.RecordTrade(2, d, TradeDirection.Sell, dayLineItem.CLOSE, bout.BuyInfo.Amount, backtestParam.Volumecommission, backtestParam.Stampduty, "主力线突破高位且增幅减缓" + mainFunddiff.ToString("F3")); break; } //计算线性回归斜率 int begin = dayFunds.IndexOf(buyDate); int end = dayFundIndex; List <double> list1 = new List <double>(); for (int k = begin; k <= end; k++) { list1.Add(dayFunds[k].Value[0]); } double fundT = list1.Normalization().SLOPE(); begin = kline.IndexOf(buyDate); end = dayKLineIndex; List <double> list2 = new List <double>(); for (int k = begin; k <= end; k++) { list2.Add(kline[k].CLOSE); } double closeT = list2.Normalization().SLOPE(); //log.Info("斜率=" + fundT.ToString("F3") + "-" + closeT.ToString("F3") + "=" + Math.Abs(fundT - closeT).ToString("F3")); //两个线性回归斜率不一致 if (Math.Abs(fundT - closeT) >= sell_slopediff) { is_slope_run -= 1; } else //两个线性回归斜率一致 { if (fundT <= sell_slopepoint) { KLineItem prevKlineItem = kline[dayKLineIndex - 1]; if (prevKlineItem.CLOSE > dayLineItem.CLOSE)//价格下降了 { if (earnRate > 0) { bout.RecordTrade(2, d, TradeDirection.Sell, dayLineItem.CLOSE, bout.BuyInfo.Amount, backtestParam.Volumecommission, backtestParam.Stampduty, "斜率一致且增幅小于阈值(" + fundT.ToString("F2") + "<" + sell_slopepoint.ToString("F2")); break; } } /*if(earnRate>0) * { * bout.RecordTrade(2, d, TradeDirection.Sell, dayLineItem.CLOSE, bout.BuyInfo.Amount, backtestParam.volumecommission, backtestParam.stampduty, "斜率一致且增幅小于阈值("+ fundT.ToString("F2")+"<"+ sell_slopepoint.ToString("F2")); * break; * }*/ } } //进入下一天 d = d.AddDays(1); days += 1; continue; } return(false); }
public override TradeRecords Execute(string code, Properties strategyParam, BacktestParameter backtestParam, ISeller seller = null) { IndicatorRepository repository = (IndicatorRepository)backtestParam.Get <Object>("repository"); if (repository == null) { return(null); } //创建数据集 TimeSerialsDataSet ds = repository[code]; if (ds == null) { return(null); } KLine klineDay = ds.DayKLine; if (klineDay == null || klineDay.Count < 0) { return(null); } TimeSeries <ITimeSeriesItem <List <double> > > fundDay = ds.DayFundTrend; if (fundDay == null || fundDay.Count <= 0) { return(null); } double p_mainforcelow = strategyParam.Get <double>("mainforcelow"); int p_monthbutpt = strategyParam.Get <int>("monthbutpt", 0); //double p_mainforceclimb = strategyParam.Get<double>("mainforceclimb"); double p_mainforceslope = strategyParam.Get <double>("mainforceslope"); int p_mainforcerough = strategyParam.Get <int>("mainforcerough"); int p_buypointdays = strategyParam.Get <int>("buypointdays"); int p_maxbuynum = strategyParam.Get <int>("maxbuynum"); GetInMode p_fundpergetin = GetInMode.Parse(strategyParam.Get <String>("getinMode")); TradeRecords tradeRecords = new TradeRecords(code); //遍历回测中的每一天 DateTime d = backtestParam.BeginDate; int beginIndex = klineDay.IndexOf(d, true); if (beginIndex < 0) { return(tradeRecords); } for (int index = beginIndex; index < klineDay.Count; index++) { KLineItem klineItemDay = klineDay[index]; if (klineItemDay == null) { continue; } d = klineItemDay.Date; ITimeSeriesItem <List <double> > fundItemDay = fundDay[d]; if (fundItemDay == null) { continue; } int fIndex = fundDay.IndexOf(fundItemDay); //是否进入到主力线低位 if (p_mainforcelow != 0 && fundItemDay.Value[0] >= p_mainforcelow) { continue; } //是否主力线爬升离开低位 if (p_mainforcelow != 0) { for (fIndex = fIndex + 1; fIndex < fundDay.Count; fIndex++) { fundItemDay = fundDay[fIndex]; if (fundItemDay == null) { continue; } if (fundItemDay.Value[0] <= p_mainforcelow) { continue; } if (fundItemDay.Date < backtestParam.BeginDate || fundItemDay.Date > backtestParam.EndDate)//数据错误 { return(tradeRecords); } d = fundItemDay.Date; index = klineDay.IndexOf(d); klineItemDay = klineDay[index]; break; } if (fIndex >= fundDay.Count) { return(tradeRecords); } } //看主力线爬升速度 if (p_mainforceslope != 0 && fIndex > 0) { //爬升速度不够快 if ((fundItemDay.Value[0] - fundDay[fIndex - 1].Value[0]) < p_mainforceslope) { continue; } } //看主力线是否持续爬升 if (p_mainforcerough > 0) { bool cont = true; for (int temp = 0; temp < p_mainforcerough; temp++) { fIndex += temp; if (fIndex >= fundDay.Count) { cont = false; break; } fundItemDay = fundDay[fIndex]; if (fundItemDay.Value[0] < fundDay[fIndex - 1].Value[0]) { cont = false; break; } } if (!cont) { continue; } d = fundItemDay.Date; index = klineDay.IndexOf(d); klineItemDay = klineDay[index]; } //看是否在买点附近 TradingLine tradingLine = ds.DayTradeLine; if (p_buypointdays >= 0 && tradingLine != null && tradingLine.buysellPoints != null && tradingLine.buysellPoints.Count > 0) { int bsptIndex = tradingLine.buysellPoints.IndexOf(d, true); ITimeSeriesItem <char> bsptItemDay = bsptIndex < 0 ? null : tradingLine.buysellPoints[bsptIndex]; if (bsptItemDay != null && bsptItemDay.Value == 'S') { bsptItemDay = bsptIndex >= tradingLine.buysellPoints.Count - 1 ? null : tradingLine.buysellPoints[bsptIndex + 1]; } if (bsptItemDay == null || (bsptItemDay.Date.Date - d).TotalDays > p_buypointdays) { continue; } } //月线买点才能买入 TimeSeries <ITimeSeriesItem <char> > ptMonths = ds.CubePtCreateOrLoad(TimeUnit.month); if (p_monthbutpt == 1 && ptMonths != null && ptMonths.Count > 0) { int t1 = 0; for (; t1 < ptMonths.Count - 1; t1++) { if (d.Date >= ptMonths[t1].Date.Date && d.Date <= ptMonths[t1 + 1].Date.Date) { break; } } if (t1 < ptMonths.Count - 1) { if (ptMonths[t1].Value != 'B') { continue; } } } //准备执行买入 String reason = ""; double price = klineItemDay.CLOSE; double fund = p_fundpergetin.Value;// price * p_maxholdnum; int amount = (int)(fund / price); TradeBout newBout = new TradeBout(ds.Code); newBout.RecordTrade(1, d, TradeDirection.Buy, price, amount, backtestParam.Volumecommission, 0, reason); tradeRecords.Bouts.Add(newBout); } return(tradeRecords); }