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

     1  package factors
     2  
     3  import (
     4  	"gitee.com/quant1x/engine/cache"
     5  	"gitee.com/quant1x/engine/datasource/base"
     6  	"gitee.com/quant1x/exchange"
     7  	"gitee.com/quant1x/gox/api"
     8  	"gitee.com/quant1x/num"
     9  	"gitee.com/quant1x/pandas"
    10  )
    11  
    12  // BasicKLine 基础日K线
    13  func BasicKLine(securityCode string) pandas.DataFrame {
    14  	securityCode = exchange.CorrectSecurityCode(securityCode)
    15  	filename := cache.KLineFilename(securityCode)
    16  	df := pandas.ReadCSV(filename)
    17  	return df
    18  }
    19  
    20  // KLine 加载日K线宽表
    21  func KLine(securityCode string) pandas.DataFrame {
    22  	securityCode = exchange.CorrectSecurityCode(securityCode)
    23  	filename := cache.WideFilename(securityCode)
    24  	df := pandas.ReadCSV(filename)
    25  	return df
    26  }
    27  
    28  // KLineToWeekly 日线转周线
    29  //
    30  //	deprecated: 不推荐使用
    31  func KLineToWeekly(kline pandas.DataFrame) pandas.DataFrame {
    32  	// 周线
    33  	var df pandas.DataFrame
    34  	//date,open,close,high,low,volume,amount,up,down
    35  	var wdate string
    36  	var o, c, h, l, v, a num.DType
    37  	var bv, sv, ba, sa num.DType
    38  	var prevClose num.DType
    39  	for i := 0; i < kline.Nrow(); i++ {
    40  		m := kline.IndexOf(i)
    41  		//date,open,close,high,low,volume,amount,up,down
    42  		// 周线日期以最后一天的日期为准
    43  		_date, ok := m["date"].(string)
    44  		if ok {
    45  			wdate = _date
    46  		}
    47  		// 周线开盘价以第一天OPEN为准
    48  		_open, ok := m["open"].(num.DType)
    49  		if ok && o == num.DType(0) {
    50  			o = _open
    51  		}
    52  		// 周线的收盘价以本周最后一个交易日的CLOSE为准
    53  		_close, ok := m["close"].(num.DType)
    54  		if ok {
    55  			c = _close
    56  		}
    57  		// 涨幅
    58  		zf := (c/prevClose - 1.00) * 100.00
    59  		_high, ok := m["high"].(num.DType)
    60  		if ok && h == num.DType(0) {
    61  			h = _high
    62  		}
    63  		if h < _high {
    64  			h = _high
    65  		}
    66  		_low, ok := m["low"].(num.DType)
    67  		if ok && l == num.DType(0) {
    68  			l = _low
    69  		}
    70  		if l > _low {
    71  			l = _low
    72  		}
    73  		_vol, ok := m["volume"]
    74  		if ok {
    75  			v += num.Any2DType(_vol)
    76  		}
    77  		_amount, ok := m["amount"].(num.DType)
    78  		if ok {
    79  			a += _amount
    80  		}
    81  		_bv, ok := m["bv"]
    82  		if ok {
    83  			bv += num.Any2DType(_bv)
    84  		}
    85  		_sv, ok := m["sv"]
    86  		if ok {
    87  			sv += num.Any2DType(_sv)
    88  		}
    89  		_ba, ok := m["ba"]
    90  		if ok {
    91  			ba += num.Any2DType(_ba)
    92  		}
    93  		_sa, ok := m["sa"]
    94  		if ok {
    95  			sa += num.Any2DType(_sa)
    96  		}
    97  		dt, _ := api.ParseTime(wdate)
    98  		w := int(dt.Weekday())
    99  		last := false
   100  		today := exchange.IndexToday()
   101  		if wdate == today {
   102  			last = true
   103  		}
   104  		// 如果是周五
   105  		if !last && w == 5 {
   106  			last = true
   107  		}
   108  		if !last {
   109  			nextDate := exchange.NextTradeDate(wdate)
   110  			ndt, _ := api.ParseTime(nextDate)
   111  			nw := int(ndt.Weekday())
   112  			if nw < w || api.DifferDays(ndt, dt) >= 7 {
   113  				last = true
   114  			}
   115  		}
   116  		if last {
   117  			df0 := pandas.NewDataFrame(
   118  				pandas.NewSeriesWithType(pandas.SERIES_TYPE_STRING, "date", wdate),
   119  				pandas.NewSeriesWithType(pandas.SERIES_TYPE_DTYPE, "open", o),
   120  				pandas.NewSeriesWithType(pandas.SERIES_TYPE_DTYPE, "close", c),
   121  				pandas.NewSeriesWithType(pandas.SERIES_TYPE_DTYPE, "high", h),
   122  				pandas.NewSeriesWithType(pandas.SERIES_TYPE_DTYPE, "low", l),
   123  				pandas.NewSeriesWithType(pandas.SERIES_TYPE_DTYPE, "volume", v),
   124  				pandas.NewSeriesWithType(pandas.SERIES_TYPE_DTYPE, "amount", a),
   125  				pandas.NewSeriesWithType(pandas.SERIES_TYPE_DTYPE, "bv", bv),
   126  				pandas.NewSeriesWithType(pandas.SERIES_TYPE_DTYPE, "sv", sv),
   127  				pandas.NewSeriesWithType(pandas.SERIES_TYPE_DTYPE, "ba", ba),
   128  				pandas.NewSeriesWithType(pandas.SERIES_TYPE_DTYPE, "sa", sa),
   129  				pandas.NewSeriesWithType(pandas.SERIES_TYPE_DTYPE, "zf", zf),
   130  			)
   131  			df = df.Concat(df0)
   132  			wdate = ""
   133  			prevClose = c
   134  			o = num.DType(0)
   135  			c = num.DType(0)
   136  			h = num.DType(0)
   137  			l = num.DType(0)
   138  			v = num.DType(0)
   139  			a = num.DType(0)
   140  		}
   141  	}
   142  	return df
   143  }
   144  
   145  // MovingAverage 移动平均线(MA)
   146  type MovingAverage struct {
   147  	MA5  float64 // 5日均线
   148  	MA10 float64 // 10日均线
   149  	MA20 float64 // 20日均线
   150  }
   151  
   152  // 由日线计算日线以上级别的K线
   153  func periodKLine(checkPeriod func(date ...string) (s, e string), securityCode string, cacheKLine ...[]base.KLine) (df pandas.DataFrame) {
   154  	baseKLines := []base.KLine{}
   155  	if len(cacheKLine) > 0 {
   156  		baseKLines = cacheKLine[0]
   157  	} else {
   158  		baseKLines = base.LoadBasicKline(securityCode)
   159  	}
   160  	if len(baseKLines) == 0 {
   161  		return
   162  	}
   163  
   164  	var klines []base.KLine
   165  	var kline base.KLine
   166  	length := len(baseKLines)
   167  	for i, v := range baseKLines {
   168  		// 确定时间, 周线的日期是本周内最后一个交易日
   169  		if len(kline.Date) == 0 {
   170  			// 重新计算周线, 先确认周线范围
   171  			ws, we := checkPeriod(v.Date)
   172  			_ = ws
   173  			//dates := trading.TradeRange(ws, we)
   174  			//days := len(dates)
   175  			//days = 7
   176  			//if days > 0 {
   177  			periodLastDate := exchange.FixTradeDate(we)
   178  			//if periodLastDate == "2023-07-30" {
   179  			//	fmt.Println(1)
   180  			//}
   181  			offset := i
   182  			for {
   183  				destDate := baseKLines[offset].Date
   184  				if destDate < periodLastDate {
   185  					offset++
   186  				}
   187  				if offset >= length {
   188  					periodLastDate = destDate
   189  					break
   190  				} else if baseKLines[offset].Date == periodLastDate {
   191  					periodLastDate = baseKLines[offset].Date
   192  					break
   193  				} else if baseKLines[offset].Date > periodLastDate {
   194  					periodLastDate = destDate
   195  					break
   196  				}
   197  			}
   198  			kline.Date = periodLastDate
   199  			//} else {
   200  			//	return
   201  			//}
   202  		}
   203  		// 周线开盘价以第一天OPEN为准
   204  		if kline.Open == num.DType(0) {
   205  			kline.Open = v.Open
   206  		}
   207  		// 周线的收盘价以本周最后一个交易日的CLOSE为准
   208  		kline.Close = v.Close
   209  		if kline.High == num.DType(0) {
   210  			kline.High = v.High
   211  		} else if kline.High < v.High {
   212  			kline.High = v.High
   213  		}
   214  		if kline.Low == num.DType(0) {
   215  			kline.Low = v.Low
   216  		} else if kline.Low > v.Low {
   217  			kline.Low = v.Low
   218  		}
   219  		kline.Volume += v.Volume
   220  		kline.Amount += v.Amount
   221  
   222  		// 切换下一周
   223  		if kline.Date == v.Date || i+1 >= len(baseKLines) {
   224  			kline.Date = v.Date
   225  			klines = append(klines, kline)
   226  			kline = base.KLine{}
   227  		}
   228  	}
   229  	df = pandas.LoadStructs(klines)
   230  	//fmt.Println(df)
   231  	return
   232  }
   233  
   234  // WeeklyKLine 周线
   235  func WeeklyKLine(securityCode string, cacheKLine ...[]base.KLine) (df pandas.DataFrame) {
   236  	return periodKLine(api.GetWeekDay, securityCode, cacheKLine...)
   237  }
   238  
   239  // MonthlyKLine 月K线
   240  func MonthlyKLine(securityCode string, cacheKLine ...[]base.KLine) (df pandas.DataFrame) {
   241  	return periodKLine(api.GetMonthDay, securityCode, cacheKLine...)
   242  }