1 Star 3 Fork 4

海风 / gotap_dipper

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
trade_ext.go 8.10 KB
一键复制 编辑 原始数据 按行查看 历史
海风 提交于 2023-10-19 17:17 . 更新: MapPositionSummary 用 Key()
package trade
import (
"errors"
"fmt"
"sync"
"github.com/sirupsen/logrus"
)
type TradeExt struct {
*Trade
AccountID string
chReady chan struct{}
// 品种@类型@交易所
//
// ("%s@%c@%s", info.CommodityNo.String(), info.CommodityType, info.ExchangeNo.String())
Product map[string]TapAPICommodityInfo
// 品种@合约1@合约2@类型@交易所@CP@行权价
//
// ("%s@%s@%s@%c@%s@%c@%s", info.CommodityNo.String(), info.ContractNo1.String(), info.ContractNo2.String(), info.CommodityType, info.ExchangeNo.String(), info.CallOrPutFlag1, info.StrikePrice1.String())
Instrument map[string]TapAPITradeContractInfo
// ("%s@%s@%c@%s", info.CommodityNo.String(), info.ContractNo.String(), info.CommodityType, info.ExchangeNo.String())
//
// TapAPIPositionSummary
MapPositionSummary sync.Map
// MatchNo:TapAPIFillInfo
MapTrade sync.Map
// 委托响应
// OnOrder func(info *TapAPIOrderInfo)
// 成交响应
OnTrade func(info *TapAPIFillInfo)
// 持仓响应
OnPosition func(info *TapAPIPositionSummary)
}
var ext *TradeExt
func NewTradeExt(authCode string) *TradeExt {
if ext != nil {
return ext
}
ext = new(TradeExt)
ext.chReady = make(chan struct{})
ext.Trade = NewTrade(authCode)
ext.Instrument = make(map[string]TapAPITradeContractInfo)
ext.Product = make(map[string]TapAPICommodityInfo)
return ext
}
func (t *TradeExt) ReqConnect(tradeIP string, port uint) error {
t.OnRspQryCommodity = func(sessionID TAPIUINT32, errorCode TAPIINT32, isLast TAPIYNFLAG, info *TapAPICommodityInfo) {
if info != nil {
key := fmt.Sprintf("%s@%c@%s", info.CommodityNo.String(), info.CommodityType, info.ExchangeNo.String())
if _, exists := t.Product[key]; exists {
fmt.Println(key, " exists!")
} else {
t.Product[key] = *info
}
}
if isLast == APIYNFLAG_YES {
fmt.Println("查询品种结束")
var s TAPIUINT32
res := t.QryContract(&s, &TapAPICommodity{}) // 查合约
if res != 0 {
fmt.Println("查合约: ", t.GetITapErrorDescribe(FromCint32(res)))
// 登录成功通知
t.chReady <- struct{}{}
}
}
}
t.OnRspQryContract = func(sessionID TAPIUINT32, errorCode TAPIINT32, isLast TAPIYNFLAG, info *TapAPITradeContractInfo) {
if info != nil {
// key := fmt.Sprintf("%s@%s@%c@%s", info.CommodityNo.String(), info.ContractNo1.String(), info.CommodityType)
// if info.CommodityType == "" {
key := fmt.Sprintf("%s@%s@%s@%c@%s@%c@%s", info.CommodityNo.String(), info.ContractNo1.String(), info.ContractNo2.String(), info.CommodityType, info.ExchangeNo.String(), info.CallOrPutFlag1, info.StrikePrice1.String())
// }
if _, exists := t.Instrument[key]; exists {
fmt.Println(key, " is Exists!")
} else {
t.Instrument[key] = *info
}
}
if isLast == APIYNFLAG_YES {
fmt.Printf("查合约结束: %d 条\n", len(t.Instrument))
var s TAPIUINT32
f := TapAPIPositionQryReq{}
copy(f.AccountNo[:], []byte(t.AccountID))
res := t.QryPositionSummary(&s, &f)
if res != 0 {
fmt.Println("查持仓: ", t.GetITapErrorDescribe(FromCint32(res)))
// 登录成功通知
t.chReady <- struct{}{}
}
}
}
t.OnRspQryPositionSummary = func(sessionID TAPIUINT32, errorCode TAPIINT32, isLast TAPIYNFLAG, info *TapAPIPositionSummary) {
if info != nil {
t.MapPositionSummary.Store(info.Key(), *info)
}
if isLast == APIYNFLAG_YES {
// 登录成功通知
t.chReady <- struct{}{}
}
}
t.OnAPIReady = func(errorCode TAPIINT32) {
if errorCode.Int32() == 0 {
var s TAPIUINT32
res := t.QryCommodity(&s) // 查品种
if res != 0 {
fmt.Println("查品种: ", t.GetITapErrorDescribe(FromCint32(res)))
// 登录成功通知
t.chReady <- struct{}{}
}
} else {
logrus.Error(t.GetITapErrorDescribe(errorCode))
}
}
t.OnConnect = func(HostAddress string) {
fmt.Println("连接前置: ", HostAddress)
}
t.OnRspLogin = func(errorCode TAPIINT32, loginRspInfo *TapAPITradeLoginRspInfo) {
if errorCode.Int32() == 0 {
fmt.Printf("%+v\n", *loginRspInfo)
} else {
fmt.Printf("登录错误: {%d:%s}\n", errorCode.Int32(), t.GetITapErrorDescribe(errorCode))
}
}
t.OnDisconnect = func(reasonCode TAPIINT32) {
fmt.Printf("断开: {%d:%s}\n", reasonCode.Int32(), t.GetITapErrorDescribe(reasonCode))
}
t.OnRtnPosition = func(info *TapAPIPositionInfo) {
fmt.Printf("OnRtnPosition: %+v", info)
}
t.OnRtnPositionProfit = func(info *TapAPIPositionProfitNotice) {
// fmt.Printf("OnRtnPositionProfit: %+v", *info)
}
t.OnRtnPositionSummary = func(info *TapAPIPositionSummary) {
t.MapPositionSummary.Store(info.Key(), *info)
if t.OnPosition != nil {
t.OnPosition(info)
}
}
t.OnRspOrderAction = func(sessionID TAPIUINT32, errorCode TAPIINT32, info *TapAPIOrderActionRsp) {
fmt.Println(info.ActionType)
}
t.OnRtnOrder = func(info *TapAPIOrderInfoNotice) {
fmt.Printf("OnRtnOrder {%d:%s}\n", info.ErrorCode.Uint32(), t.GetITapErrorDescribe(TAPIINT32(info.ErrorCode)))
}
t.OnRtnSpecialOrder = func(info *TapAPISpecialOrderInfo) {
fmt.Printf("OnRtnSpecialOrder %+v\n", *info)
}
t.OnRtnFill = func(info *TapAPIFillInfo) {
if t.OnTrade == nil {
// fmt.Printf("OnRtnFill %+v\n", *info)
t.MapTrade.Store(info.MatchNo, *info)
} else {
t.OnTrade(info)
}
}
if res := t.SetHostAddress(tradeIP, TAPIUINT16(port)); res != 0 {
msg := t.GetITapErrorDescribe(FromCint32(res))
return errors.New(msg)
}
return nil
}
func (t *TradeExt) ReqLogin(accountNo, passWord string) error {
logAuth := TapAPITradeLoginAuth{
ISModifyPassword: APIYNFLAG_NO,
}
copy(logAuth.UserNo[:], accountNo)
copy(logAuth.Password[:], passWord)
if res := t.Login(&logAuth); res != 0 {
msg := t.GetITapErrorDescribe(FromCint32(res))
return errors.New(msg)
}
<-t.chReady
t.AccountID = accountNo
return nil
}
func (t *TradeExt) ReqOrderInsert(exchangeID, commodityNo, contractNo string, orderType TAPIOrderTypeType, price float64, qty int, side TAPISideType, commodityType TAPICommodityType) (session uint, clientNo string, err error) {
var order = TapAPINewOrder{}
copy(order.AccountNo[:], []byte(t.AccountID))
copy(order.ExchangeNo[:], []byte(exchangeID))
copy(order.CommodityNo[:], []byte(commodityNo))
copy(order.ContractNo[:], []byte(contractNo))
// copy(order.ContractNo2[:], contractNo) // 提示: 下单无效的合约
order.OrderType = orderType // 限价 市价...
order.OrderPrice = FromFloat64(price)
order.OrderQty = FromUint32(uint32(qty))
order.OrderMinQty = FromUint32(uint32(1))
order.HedgeFlag = TAPI_HEDGEFLAG_NONE
// order.ClientID
// order.ExpireTime // GTD 时使用
order.TimeInForce = TAPI_ORDER_TIMEINFORCE_GFD
order.OrderSide = side // 买卖
order.CommodityType = commodityType // 品种类型
order.CallOrPutFlag = TAPI_CALLPUT_FLAG_NONE
order.CallOrPutFlag2 = TAPI_CALLPUT_FLAG_NONE
order.TimeInForce = TAPI_ORDER_TIMEINFORCE_GFD // 有效期
order.IsRiskOrder = APIYNFLAG_NO
order.PositionEffect = TAPI_PositionEffect_NONE
order.PositionEffect2 = TAPI_PositionEffect_NONE
order.HedgeFlag = TAPI_HEDGEFLAG_NONE
// {-12035:输入错误的:TAPITacticsTypeType}
// order.TacticsType = TAPI_TACTICS_TYPE_ATUO
order.TacticsType = TAPI_TACTICS_TYPE_NONE // 策略单类型
order.OrderSource = TAPI_ORDER_SOURCE_PROGRAM // 来源
order.AddOneIsValid = APIYNFLAG_NO
order.TriggerCondition = TAPI_TRIGGER_CONDITION_NONE
order.TriggerPriceType = TAPI_TRIGGER_PRICE_NONE
var s TAPIUINT32
var c TAPISTR_50
res := t.InsertOrder(&s, &c, &order)
if res != 0 {
err = fmt.Errorf("委托: {%d:%s}", res, t.GetITapErrorDescribe(FromCint32(res)))
return
}
session = uint(s.Uint32())
clientNo = c.String()
return
}
func (t *TradeExt) ReqOrderInsertLMT(exchangeID, commodityNo, contractNo string, price float64, qty int, side TAPISideType, commodityType TAPICommodityType) (session uint, clientNo string, err error) {
return t.ReqOrderInsert(exchangeID, commodityNo, contractNo, TAPI_ORDER_TYPE_LIMIT, price, qty, side, commodityType)
}
func (t *TradeExt) ReqOrderInsertMKT(exchangeID, commodityNo, contractNo string, qty int, side TAPISideType, commodityType TAPICommodityType) (session uint, clientNo string, err error) {
return t.ReqOrderInsert(exchangeID, commodityNo, contractNo, TAPI_ORDER_TYPE_MARKET, 0, qty, side, commodityType)
}
Go
1
https://gitee.com/haifengat/gotap_dipper.git
git@gitee.com:haifengat/gotap_dipper.git
haifengat
gotap_dipper
gotap_dipper
v0.0.3

搜索帮助