gitee.com/quant1x/engine@v1.8.4/models/snapshot_tick.go (about)

     1  package models
     2  
     3  import (
     4  	"gitee.com/quant1x/engine/factors"
     5  	"gitee.com/quant1x/exchange"
     6  	"gitee.com/quant1x/gotdx"
     7  	"gitee.com/quant1x/gotdx/quotes"
     8  	"gitee.com/quant1x/gotdx/securities"
     9  	"gitee.com/quant1x/gox/api"
    10  	"gitee.com/quant1x/gox/logger"
    11  	"gitee.com/quant1x/gox/progressbar"
    12  	"gitee.com/quant1x/num"
    13  	"sync"
    14  )
    15  
    16  var (
    17  	__mutexTicks sync.RWMutex
    18  	__cacheTicks = map[string]quotes.Snapshot{}
    19  )
    20  
    21  // GetTickFromMemory 获取快照缓存
    22  func GetTickFromMemory(securityCode string) *quotes.Snapshot {
    23  	__mutexTicks.RLock()
    24  	v, found := __cacheTicks[securityCode]
    25  	__mutexTicks.RUnlock()
    26  	if found {
    27  		return &v
    28  	}
    29  	return nil
    30  }
    31  
    32  // GetStrategySnapshot 从缓存中获取快照
    33  func GetStrategySnapshot(securityCode string) *factors.QuoteSnapshot {
    34  	v := GetTickFromMemory(securityCode)
    35  	if v == nil || v.State != quotes.TDX_SECURITY_TRADE_STATE_NORMAL {
    36  		// 非正常交易的记录忽略掉
    37  		return nil
    38  	}
    39  	snapshot := factors.QuoteSnapshot{}
    40  	_ = api.Copy(&snapshot, &v)
    41  	snapshot.Name = securities.GetStockName(securityCode)
    42  	//snapshot.Code = securityCode
    43  	snapshot.OpeningChangeRate = num.NetChangeRate(snapshot.LastClose, snapshot.Open)
    44  	snapshot.ChangeRate = num.NetChangeRate(snapshot.LastClose, snapshot.Price)
    45  	f10 := factors.GetL5F10(securityCode)
    46  	if f10 != nil {
    47  		snapshot.Capital = f10.Capital
    48  		snapshot.FreeCapital = f10.FreeCapital
    49  		snapshot.OpenTurnZ = f10.TurnZ(snapshot.OpenVolume)
    50  	}
    51  	history := factors.GetL5History(securityCode)
    52  	if history != nil {
    53  		lastMinuteVolume := history.GetMV5()
    54  		snapshot.OpenQuantityRatio = float64(snapshot.OpenVolume) / lastMinuteVolume
    55  		minuteVolume := float64(snapshot.Vol) / float64(exchange.Minutes(snapshot.Date))
    56  		snapshot.QuantityRatio = minuteVolume / lastMinuteVolume
    57  	}
    58  	snapshot.OpenBiddingDirection, snapshot.OpenVolumeDirection = v.CheckDirection()
    59  	return &snapshot
    60  }
    61  
    62  // SyncAllSnapshots 实时更新快照
    63  func SyncAllSnapshots(barIndex *int) {
    64  	modName := "同步快照数据"
    65  	allCodes := securities.AllCodeList()
    66  	count := len(allCodes)
    67  	var bar *progressbar.Bar = nil
    68  	if barIndex != nil {
    69  		bar = progressbar.NewBar(*barIndex, "执行["+modName+"]", count)
    70  	}
    71  	currentDate := exchange.GetCurrentlyDay()
    72  	tdxApi := gotdx.GetTdxApi()
    73  	parallelCount := tdxApi.NumOfServers()
    74  	parallelCount /= 2
    75  	if parallelCount < 2 {
    76  		parallelCount = 2
    77  	}
    78  	var snapshots []quotes.Snapshot
    79  	var wg sync.WaitGroup
    80  	var mutex sync.Mutex
    81  	codeCh := make(chan []string, parallelCount)
    82  
    83  	// 启动goroutine来处理快照获取
    84  	for i := 0; i < parallelCount; i++ {
    85  		go func() {
    86  			for subCodes := range codeCh {
    87  				for i := 0; i < quotes.DefaultRetryTimes; i++ {
    88  					list, err := tdxApi.GetSnapshot(subCodes)
    89  					if err != nil {
    90  						logger.Errorf("ZS: 网络异常: %+v, 重试: %d", err, i+1)
    91  						continue
    92  					}
    93  					mutex.Lock()
    94  					for _, v := range list {
    95  						// 修订日期
    96  						v.Date = currentDate
    97  						snapshots = append(snapshots, v)
    98  					}
    99  					mutex.Unlock()
   100  
   101  					break
   102  				}
   103  			}
   104  			wg.Done()
   105  		}()
   106  	}
   107  
   108  	for start := 0; start < count; start += quotes.TDX_SECURITY_QUOTES_MAX {
   109  		length := count - start
   110  		if length >= quotes.TDX_SECURITY_QUOTES_MAX {
   111  			length = quotes.TDX_SECURITY_QUOTES_MAX
   112  		}
   113  		var subCodes []string
   114  		for i := 0; i < length; i++ {
   115  			securityCode := allCodes[start+i]
   116  			subCodes = append(subCodes, securityCode)
   117  			if barIndex != nil {
   118  				bar.Add(1)
   119  			}
   120  		}
   121  		if len(subCodes) == 0 {
   122  			continue
   123  		}
   124  		codeCh <- subCodes
   125  	}
   126  	// channel 关闭后, 仍然可以读, 一直到读完全部数据
   127  	close(codeCh)
   128  
   129  	wg.Add(parallelCount)
   130  	wg.Wait()
   131  	// 如果有进度条
   132  	if bar != nil {
   133  		// 等待进度条结束
   134  		bar.Wait()
   135  	}
   136  
   137  	__mutexTicks.Lock()
   138  	for _, v := range snapshots {
   139  		__cacheTicks[v.SecurityCode] = v
   140  	}
   141  	__mutexTicks.Unlock()
   142  
   143  	if barIndex != nil {
   144  		*barIndex++
   145  	}
   146  }