dev 5
This commit is contained in:
152
go-client/apps/trend/logic/state.go
Normal file
152
go-client/apps/trend/logic/state.go
Normal file
@@ -0,0 +1,152 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"slices"
|
||||
"sync"
|
||||
|
||||
"big-qmt/go-client/config"
|
||||
"big-qmt/go-client/sdk"
|
||||
)
|
||||
|
||||
var (
|
||||
StatusNone = ""
|
||||
StatusIng = "ING" // 处理中
|
||||
StatusOk = "OK" // 成功
|
||||
QuantState *State
|
||||
)
|
||||
|
||||
type State struct {
|
||||
AbsPath string
|
||||
mu sync.Mutex
|
||||
Items map[string]*StateItem
|
||||
Codes []string
|
||||
}
|
||||
|
||||
type StateItem struct {
|
||||
Code string `json:"code"`
|
||||
BaseOrderId string `json:"base_order_id"`
|
||||
BaseQty int `json:"base_qty"`
|
||||
BaseCost float64 `json:"base_cost"`
|
||||
BaseStatus string `json:"base_status,omitempty"`
|
||||
AddedOrderId string `json:"added_order_id"`
|
||||
AddedNum int `json:"add_num"`
|
||||
AddedQty int `json:"add_qty"`
|
||||
AddedCost float64 `json:"add_cost"`
|
||||
AddedStatus string `json:"added_status,omitempty"`
|
||||
}
|
||||
|
||||
func InitState(sn string) error {
|
||||
absPath := path.Join(config.Global.QMTDataDir, fmt.Sprintf("%s_%s_state.json", sn, config.Account.AccountID))
|
||||
items, err := loadStateFile(absPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var codes []string
|
||||
for code, _ := range items {
|
||||
codes = append(codes, code)
|
||||
}
|
||||
|
||||
QuantState = &State{
|
||||
AbsPath: absPath,
|
||||
Items: items,
|
||||
Codes: codes,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadStateFile(fp string) (map[string]*StateItem, error) {
|
||||
raw, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("[状态] 读取失败: %v", err)
|
||||
}
|
||||
var items map[string]*StateItem
|
||||
if err := json.Unmarshal(raw, &items); err != nil {
|
||||
return nil, fmt.Errorf("[状态] 解析失败:%s", err)
|
||||
}
|
||||
return items, nil
|
||||
|
||||
}
|
||||
|
||||
func SyncPositions(positions []sdk.Position) error {
|
||||
for _, pos := range positions {
|
||||
code := pos.StockCode
|
||||
if code == "" || pos.Volume <= 0 || pos.OpenPrice <= 0 {
|
||||
continue
|
||||
}
|
||||
if !slices.Contains(QuantState.Codes, code) {
|
||||
item := &StateItem{
|
||||
Code: code,
|
||||
BaseQty: pos.Volume,
|
||||
BaseCost: pos.OpenPrice,
|
||||
BaseStatus: StatusOk,
|
||||
}
|
||||
QuantState.Append(item)
|
||||
logf("WARNING", "[状态] %s 首次接管为底仓 数量=%d 成本=%.2f", code, pos.Volume, pos.OpenPrice)
|
||||
}
|
||||
}
|
||||
|
||||
return QuantState.Save()
|
||||
}
|
||||
|
||||
func (s *State) Append(i *StateItem) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
s.Items[i.Code] = i
|
||||
s.Codes = append(s.Codes, i.Code)
|
||||
}
|
||||
|
||||
func (s *State) Get(code string) (*StateItem, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
if i, ok := s.Items[code]; ok {
|
||||
return i, nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("%s not found.", code)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *State) Set(i *StateItem) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
if _, ok := s.Items[i.Code]; !ok {
|
||||
s.Codes = append(s.Codes, i.Code)
|
||||
}
|
||||
s.Items[i.Code] = i
|
||||
}
|
||||
|
||||
func (s *State) Delete(code string) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
delete(s.Items, code)
|
||||
if index := slices.Index(s.Codes, code); index >= 0 {
|
||||
s.Codes = slices.Delete(s.Codes, index, index+1)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *State) Save() error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
// 写入AbsPath文件
|
||||
f, err := os.OpenFile(s.AbsPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("[状态] 打开文件失败: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
encoder := json.NewEncoder(f)
|
||||
encoder.SetIndent("", " ")
|
||||
if err := encoder.Encode(s.Items); err != nil {
|
||||
return fmt.Errorf("[状态] 写入失败: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user