/// <summary> /// 根据priceType(高开低收、成交量、持仓量),对input[0]进行升周期更新 /// </summary> void updatePeriodUpper(PriceType priceType, NumericSeries input) { switch (priceType) { case PriceType.H: input[0] = Math.Max(input[0], this.Highs[0]); break; case PriceType.L: input[0] = Math.Min(input[0], this.Lows[0]); break; case PriceType.O: //tmp = this.O; break; case PriceType.C: input[0] = this.Closes[0]; break; case PriceType.V: input[0] += this.Volumes[0]; break; case PriceType.I: input[0] = this.OpenInts[0]; break; } }
/// <summary> /// 指标构造器 /// </summary> /// <param name="input">输入参数序列,如对于SUM指标,输入参数序列Input就是计算对象</param> /// <param name="periods">周期参数,由于可能不止一个,所以设置为参数数组 params;对于SMA,由于周期参数只有一个,所以就只输入一个周期值</param> protected Indicator(NumericSeries input, params Numeric[] periods) { //输入序列(Input)和周期参数(Periods) this.Input = input; this.Periods = periods; //获得父类、子类(Indicator)中所有字段(field),选出DataSeries类型的实例。 var fields_In_CurrentType = GetType().GetFields(this.Bf); foreach (FieldInfo fi in fields_In_CurrentType) { bool isCustomSeries = !(NonCustomSeriesNames.IndexOf(fi.Name) >= 0); if (isCustomSeries && fi.FieldType == typeof(NumericSeries)) { NumericSeries customSeries = (NumericSeries)fi.GetValue(this); //若用户自定义序列为null则初始化 if (customSeries == null) { fi.SetValue(this, new NumericSeries()); customSeries = (NumericSeries)fi.GetValue(this); } //Value等其他用户在子类中定义的DataSeries添加到CustomSeries this.DictCustomSeries[fi.Name] = customSeries; //Value、自定义序列Input(TRs) //customSeries.Idc = this; } } }
/// <summary> /// 跨周期引用 /// </summary> /// <param name="priceType"></param> /// <param name="interval">周期数</param> /// <param name="type">周期类型:周/月/年时interval无效</param> /// <returns></returns> public NumericSeries PeriodUpper(PriceType priceType, int interval = 1, PeriodType type = PeriodType.Day) { NumericSeries rtn = new NumericSeries(); DictPeriodValue.TryAdd(new Tuple <PriceType, int, PeriodType>(priceType, interval, type), rtn); DictPeriodTime.TryAdd(new Tuple <PriceType, int, PeriodType>(priceType, interval, type), new DateTimeSeries()); return(rtn); }
/// <summary> /// 求和,包含当前元素值(Price[0]) /// </summary> /// <param name="Price"></param> /// <param name="Lenth"></param> /// <returns></returns> static public Numeric Summation(NumericSeries Price, int Lenth) { Numeric sumValue = 0; for (int i = 0; i < Lenth; i++) { sumValue += Price[i]; } return(sumValue); }
/// <summary> /// 最近pPeriod期pSeries的最小值 /// </summary> /// <param name="pSeries"></param> /// <param name="pPeriod"></param> /// <returns></returns> public Numeric Lowest(NumericSeries pSeries, Numeric pPeriod) { Numeric rtn = Numeric.MaxValue; for (int i = 0; i < pPeriod; ++i) { if (pSeries[i] < rtn) { rtn = pSeries[i]; } } return(rtn); }
/// <summary> /// 最近pPeriod期pSeries的最大值 /// </summary> /// <param name="pSeries"></param> /// <param name="pPeriod"></param> /// <returns></returns> public Numeric Highest(NumericSeries pSeries, Numeric pPeriod) { //_inds.GetOrAdd(string.Format("Highest_{0}_{1}", pSeries.SeriesName, pPeriod), new Highest(pSeries, (int) pPeriod)); Numeric rtn = Numeric.MinValue; for (int i = 0; i < pPeriod; ++i) { if (pSeries[i] > rtn) { rtn = pSeries[i]; } } return(rtn); }
/// <summary> /// 计算指定周期内的数值型序列值的平均值,如果Price序列的数量小于Length,则返回Price[0]。 /// </summary> /// <param name="Price"></param> /// <param name="Length"></param> /// <returns></returns> static public Numeric Average(NumericSeries Price, int Length) { if (Price.Count < Length) { return(Price[0]); } else { Numeric tmp = 0; for (int i = 0; i < Length; i++) { tmp += Price[i]; } return(tmp / Length); } }
/// <summary> /// 计算指定周期内的数值序列值的指数平均值,如果Price序列的数量小于Length,则返回Price[0] /// </summary> /// <returns>经过指数平均的序列</returns> static public NumericSeries XAverage(NumericSeries Price, int Length) { Numeric sFactor = 2.0 / (Length + 1); NumericSeries XAvgValues = new NumericSeries(); for (int i = 0; i < Price.Count; i++) { int j = Price.Count - i; if (i == 0) { XAvgValues.Add(Price[j - 1]); } else { XAvgValues.Add(XAvgValues[j] + sFactor * (Price[j - 1] - XAvgValues[j])); } } return(XAvgValues); }
//TB引用转换:初始化 OpenD、HighD、LowD、CloseD、MinMove、PriceScale void TBInit() { FormulaName = this.Name; //新建一天级别的 OpenD、HighD、LowD、CloseD,并且添加到字典:DicPeriodValue、DicPeriodTime _OpenD = PeriodUpper(PriceType.O, 1, PeriodType.Day); _HighD = PeriodUpper(PriceType.H, 1, PeriodType.Day); _LowD = PeriodUpper(PriceType.L, 1, PeriodType.Day); _CloseD = PeriodUpper(PriceType.C, 1, PeriodType.Day); //最小价格变动单位 MinMove、PriceScale if (InstrumentInfo.PriceTick >= 1) { MinMove = (int)InstrumentInfo.PriceTick; } else { PriceScale = (Numeric)Math.Pow(10, -Math.Round(InstrumentInfo.PriceTick, 6).ToString().TrimEnd('0').Split('.')[1].Length); MinMove = (int)(InstrumentInfo.PriceTick / PriceScale); } }
/// <summary> /// Strategy装载BarSerieses,将历史BarSeries加入到StrategyData中 /// </summary> public void LoadBarSerieses(params BarSeries[] barSeries) { //清理StrategyData和BarSerieses this.StrategyDatas.Clear(); this.BarSerieses.Clear(); bool _real = false; foreach (BarSeries bars in barSeries) { //装载策略中使用到的BarSeries至StrategyData this.BarSerieses.Add(bars); StrategyData sd = new StrategyData(bars); //每当上个Bar完成更新,则调用策略更新 bars.OnLastBarComplete += this.UpdateStrategy; //sd.OnRtnOrder += (o, d) => //{ // if (_rtnOrder != null && _real) // _rtnOrder(o, d, this); //}; this.StrategyDatas.Add(sd); } //初始化TB相关数据,初始化 OpenD、HighD、LowD、CloseD、MinMove、PriceScale TBInit(); //调用客户初始化函数 this.Initialize(); #region ==========初始化所有指标和用户自定义序列========== //所有指标赋值 this._indicators.Clear(); foreach (var idx in GetType().GetFields(this.Bf) .Where(n => n.FieldType.BaseType == typeof(Indicator))) { Indicator i = (Indicator)idx.GetValue(this); if (i == null) { throw new Exception("指标未初始化!"); } this._indicators.Add(i); } //【添加】重置所有指标的输入,指向新的new 的 strategyData foreach (var i in this._indicators) { ResetInput(i, true); } //所有用户自定义序列 this._costomSeries.Clear(); var fields_In_CurrentType = GetType().GetFields(this.Bf).Where(n => n.FieldType == typeof(NumericSeries)).ToArray(); foreach (var fi in fields_In_CurrentType) { //非K线数据:存入 if (this.NonCustomSeriesNames.IndexOf((string)fi.GetType().GetProperty("Name").GetValue(fi, null)) >= 0) { continue; } NumericSeries customSeries = (NumericSeries)fi.GetValue(this); if (customSeries == null) { fi.SetValue(this, new NumericSeries()); } this._costomSeries.Add((NumericSeries)fi.GetValue(this)); //setvalue后要重新getvalue } #endregion ==========初始化所有指标和用户自定义序列========== //this.Test(); _real = true; //控制实盘发单 //this.Initialize(); //再次调用客户初始化函数: 首次调用时,数据源不正确 }
/// <summary> /// Strategy在调用其Update时,执行该函数。根据周期类型,更新DicPeriodTime、DicPeriodValue /// </summary> void periodUpper() { foreach (var item in this.DictPeriodValue) { NumericSeries tmp = null; switch (item.Key.Item1) { case PriceType.H: tmp = this.Highs; break; case PriceType.L: tmp = this.Lows; break; case PriceType.O: tmp = this.Opens; break; case PriceType.C: tmp = this.Closes; break; case PriceType.V: tmp = this.Volumes; break; case PriceType.I: tmp = this.OpenInts; break; } DateTime dt0 = DateTime.ParseExact(this.NumDateTimes[0].ToString("00000000.000000"), "yyyyMMdd.HHmmss", null); DateTime dtID; switch (item.Key.Item3) { case PeriodType.Minute: dtID = new DateTime(dt0.Year, dt0.Month, dt0.Day, dt0.Hour, dt0.Minute, 0); if (this.DictPeriodTime[item.Key].Count == 0 || (dt0.Minute % item.Key.Item2 == 0 && this.DictPeriodTime[item.Key][0] != dtID)) { this.DictPeriodTime[item.Key].Add(dtID); item.Value.Add(tmp[0]); } else { updatePeriodUpper(item.Key.Item1, item.Value); } break; case PeriodType.Hour: dtID = new DateTime(dt0.Year, dt0.Month, dt0.Day, dt0.Hour, 0, 0); if (this.DictPeriodTime[item.Key].Count == 0 || this.DictPeriodTime[item.Key][0] != dtID) { this.DictPeriodTime[item.Key].Add(dtID); item.Value.Add(tmp[0]); } else { updatePeriodUpper(item.Key.Item1, item.Value); } break; case PeriodType.Day: dtID = new DateTime(dt0.Year, dt0.Month, dt0.Day); if (this.DictPeriodTime[item.Key].Count == 0 || this.DictPeriodTime[item.Key][0] != dtID) { this.DictPeriodTime[item.Key].Add(dtID); item.Value.Add(tmp[0]); } else { updatePeriodUpper(item.Key.Item1, item.Value); } break; case PeriodType.Week: dtID = dt0.AddDays(1 - (int)dt0.DayOfWeek); dtID = new DateTime(dtID.Year, dtID.Month, dtID.Day); if (this.DictPeriodTime[item.Key].Count == 0 || this.DictPeriodTime[item.Key][0] != dtID) { this.DictPeriodTime[item.Key].Add(dtID); item.Value.Add(tmp[0]); } else { updatePeriodUpper(item.Key.Item1, item.Value); } break; case PeriodType.Month: dtID = new DateTime(dt0.Year, dt0.Month, 1); if (this.DictPeriodTime[item.Key].Count == 0 || this.DictPeriodTime[item.Key][0] != dtID) { this.DictPeriodTime[item.Key].Add(dtID); item.Value.Add(tmp[0]); } else { updatePeriodUpper(item.Key.Item1, item.Value); } break; case PeriodType.Year: dtID = new DateTime(dt0.Year, 1, 1); if (this.DictPeriodTime[item.Key].Count == 0 || this.DictPeriodTime[item.Key][0] != dtID) { this.DictPeriodTime[item.Key].Add(dtID); item.Value.Add(tmp[0]); break; //不执行update } else { updatePeriodUpper(item.Key.Item1, item.Value); } break; } } }