gitee.com/quant1x/engine@v1.8.4/factors/dataset_wide.go (about)

     1  package factors
     2  
     3  import (
     4  	"context"
     5  	"gitee.com/quant1x/engine/cache"
     6  	"gitee.com/quant1x/engine/datasource/base"
     7  	"gitee.com/quant1x/exchange"
     8  	"gitee.com/quant1x/gotdx/quotes"
     9  	"gitee.com/quant1x/gox/api"
    10  	"gitee.com/quant1x/num"
    11  	"slices"
    12  )
    13  
    14  // DataWideKLine 宽表
    15  type DataWideKLine struct {
    16  	Manifest
    17  }
    18  
    19  func init() {
    20  	summary := __mapDataSets[BaseWideKLine]
    21  	_ = cache.Register(&DataWideKLine{Manifest: Manifest{DataSummary: summary}})
    22  }
    23  
    24  func (this *DataWideKLine) Clone(date string, code string) DataSet {
    25  	summary := __mapDataSets[BaseWideKLine]
    26  	var dest = DataWideKLine{
    27  		Manifest: Manifest{
    28  			DataSummary: summary,
    29  			Date:        date,
    30  			Code:        code,
    31  		},
    32  	}
    33  	return &dest
    34  }
    35  
    36  func (this *DataWideKLine) Init(ctx context.Context, date string) error {
    37  	// 恢复交易数据的最早日期默认值
    38  	base.RestoreBeginDateOfHistoricalTradingData()
    39  	_ = ctx
    40  	_ = date
    41  	return nil
    42  }
    43  
    44  func (this *DataWideKLine) Update(date string) {
    45  	pullWideByDate(this.GetSecurityCode(), date)
    46  }
    47  
    48  func (this *DataWideKLine) Repair(date string) {
    49  	this.Update(date)
    50  }
    51  
    52  func (this *DataWideKLine) Increase(snapshot quotes.Snapshot) {
    53  	_ = snapshot
    54  }
    55  
    56  func (this *DataWideKLine) Print(code string, date ...string) {
    57  	_ = code
    58  	_ = date
    59  }
    60  
    61  // 通过日期拉取宽表数据
    62  func pullWideByDate(securityCode, date string) []SecurityFeature {
    63  	securityCode = exchange.CorrectSecurityCode(securityCode)
    64  	// 1. 加载缓存
    65  	filename := cache.WideFilename(securityCode)
    66  	var list []SecurityFeature
    67  	var beginDate string // 补数据的开始日期
    68  	var endDate string   // 补数据的结束日期
    69  	var cacheBeginDate, cacheEndDate string
    70  	err := api.CsvToSlices(filename, &list)
    71  	if err != nil || len(list) == 0 {
    72  		// 如果文件为空, 暂定从1990-12-19
    73  		cacheBeginDate = exchange.MARKET_CH_FIRST_LISTTIME
    74  		cacheEndDate = cacheBeginDate
    75  		beginDate = cacheBeginDate
    76  	} else {
    77  		//list = list[:len(list)-1]
    78  		cacheBeginDate = list[0].Date
    79  		last := list[len(list)-1]
    80  		cacheEndDate = last.Date
    81  		// 以缓存文件最后一条记录的日期
    82  		beginDate = cacheEndDate
    83  	}
    84  	// 2. 确定补齐数据的日期
    85  	endDate = exchange.FixTradeDate(date)
    86  	// 2.1 结束日期经过交易日历的校对处理一次
    87  	//logger.Warnf("[%s]: begin=%s, end= %s", securityCode, beginDate, endDate)
    88  	if len(beginDate) == 0 {
    89  		beginDate = exchange.MARKET_CH_FIRST_LISTTIME
    90  	}
    91  	dates := exchange.TradingDateRange(beginDate, endDate)
    92  	n := len(dates)
    93  	if n == 0 {
    94  		// 这种情况的原因是传入的date小于缓存的最后一条记录的日期
    95  		beginDate = endDate
    96  	} else if n == 1 {
    97  		// 传入日期和缓存最后一条记录的日期相同
    98  		beginDate = dates[0]
    99  		endDate = dates[0]
   100  	} else {
   101  		beginDate = dates[0]
   102  		endDate = dates[n-1]
   103  	}
   104  	// 3. 补齐日线, 日线是必须要有的, 也肯定会有
   105  	// 数据为空, 从基础K线获取K线部分
   106  	klines := base.CheckoutKLines(securityCode, endDate)
   107  	kline_length := len(klines)
   108  	if kline_length == 0 {
   109  		// K线为空, 返回空
   110  		return nil
   111  	} else {
   112  		// 校验wide缓存和k线缓存的开始日期是否对齐
   113  		klsBeginDate := klines[0].Date
   114  		klsEndDate := klines[kline_length-1].Date
   115  		if cacheBeginDate == klsBeginDate {
   116  			// 如果缓存的开始日期和k线的开始日期相同, 没有问题
   117  		} else {
   118  			// 如果缓存的开始日期和k线的开始日期不同, 则认为数据错乱, 清空
   119  			clear(list)
   120  			// 设置缓存开始日期为k线的开始日期
   121  			cacheBeginDate = klsBeginDate
   122  			// 设置缓存结束日期为k线的开始日期
   123  			cacheEndDate = klsBeginDate
   124  			beginDate = cacheBeginDate
   125  		}
   126  		_ = klsEndDate
   127  	}
   128  	// 4. 确定缓存记录数
   129  	list_length := len(list)
   130  	// 5. 如果kline比wide数据多
   131  	if kline_length > list_length {
   132  		list = slices.Grow(list, kline_length)
   133  	}
   134  	transBeginDate := base.GetBeginDateOfHistoricalTradingData()
   135  	transBeginDate = exchange.FixTradeDate(transBeginDate)
   136  	for i, v := range klines {
   137  		featureDate := v.Date
   138  		cacheDate := v.Date
   139  		// 强制更新标志
   140  		forceUpdate := false
   141  		if i < list_length && featureDate >= transBeginDate {
   142  			checksum := list[i].CheckSum()
   143  			forceUpdate = checksum == 0
   144  		}
   145  		if !forceUpdate && v.Date < beginDate {
   146  			continue
   147  		}
   148  		if v.Date > endDate {
   149  			break
   150  		}
   151  		var info SecurityFeature
   152  		// 复制k线
   153  		info.Date = v.Date
   154  		info.Open = v.Open
   155  		info.Close = v.Close
   156  		info.High = v.High
   157  		info.Low = v.Low
   158  		info.Volume = int64(v.Volume)
   159  		info.Amount = v.Amount
   160  		info.Up = v.Up
   161  		info.Down = v.Down
   162  		// 附加成交数据
   163  		if featureDate >= transBeginDate {
   164  			// 成交数据
   165  			trans := base.CheckoutTransactionData(securityCode, featureDate, true)
   166  			if len(trans) > 0 {
   167  				cover := CountInflow(trans, securityCode, featureDate)
   168  				// 修正f10的缓存, 应该是缓存日期为准
   169  				f10 := GetL5F10(securityCode, cacheDate)
   170  				if f10 != nil {
   171  					cover.OpenTurnZ = f10.TurnZ(cover.OpenVolume)
   172  					cover.CloseTurnZ = f10.TurnZ(cover.CloseVolume)
   173  				}
   174  				info.OpenVolume = cover.OpenVolume
   175  				info.OpenTurnZ = cover.OpenTurnZ
   176  				info.CloseVolume = cover.CloseVolume
   177  				info.CloseTurnZ = cover.CloseTurnZ
   178  				info.Volume = cover.InnerVolume + cover.OuterVolume
   179  				info.InnerVolume = cover.InnerVolume
   180  				info.OuterVolume = cover.OuterVolume
   181  				info.InnerAmount = cover.InnerAmount
   182  				info.OuterAmount = cover.OuterAmount
   183  			}
   184  		}
   185  		if i < list_length {
   186  			list[i] = info
   187  		} else {
   188  			list = append(list, info)
   189  		}
   190  	}
   191  	// 6. 最后再修订数据
   192  	lastClose := 0.000
   193  	for i := 0; i < len(list); i++ {
   194  		v := &list[i]
   195  		// 6.1 修正last_close和change_rate
   196  		if i == 0 {
   197  			v.LastClose = v.Open
   198  		} else {
   199  			v.LastClose = lastClose
   200  		}
   201  		v.ChangeRate = num.NetChangeRate(v.LastClose, v.Close)
   202  		lastClose = v.Close
   203  		// 6.2 修正up和down
   204  		//// 指数类, up和down对应涨跌家数
   205  		//// 股票类, 对应内外盘
   206  		//if v.Up == 0 {
   207  		//	v.Up = int(v.OuterVolume)
   208  		//}
   209  		//if v.Down == 0 {
   210  		//	v.Down = int(v.InnerVolume)
   211  		//}
   212  	}
   213  
   214  	// 7. 保存文件
   215  	_ = api.SlicesToCsv(filename, list)
   216  	return list
   217  }