goctp 7*24运行

4 篇文章 0 订阅
3 篇文章 0 订阅

逻辑

定时启停

交易所非交易停止

  • 没有状态为 continous 的合约

  • 所有交易所收盘

    • 时间 hour == 15
  • 夜盘收盘

    • 时间 hour ≤ 3

定时启动

  • 早盘 08:40

  • 夜盘 20:40

QA

柜台未启动,一直等待连接

设置timeout,达到后release

若不处理会柜台启动后自动重连,从而导致异常(柜台启动,但数据等环境未准备好)。

非交易时段启动,返回 disconnected 4097 错误

增加 release ,手动释放。

登录返回“未初始化”

原因:有夜盘,第二天早晨服务器要将夜盘数据导入,需要一定初始化时间。

解决:sleep 一段时间后重新登录

代码

package main

import (
	"fmt"
	"os"
	"time"

	"gitee.com/haifengat/goctp"
	ctp "gitee.com/haifengat/goctp/lnx"
	// ctp "gitee.com/haifengat/goctp/win"
)

/*appid:simnow_client_test
authcode:0000000000000000*/
var (
	userID     = "008107"
	password   = "1"
	brokerID   = "9999"
	appID      = "simnow_client_test"
	authCode   = "0000000000000000"
	tradeFront = "tcp://180.168.146.187:10202"
	quoteFront = "tcp://180.168.146.187:10212"
	// tradeFront = "tcp://180.168.146.187:10130"
	// quoteFront = "tcp://180.168.146.187:10131"
)

var t *ctp.Trade
var q *ctp.Quote

func init() {
	if tmp := os.Getenv("userID"); tmp != "" {
		userID = tmp
	}
	if tmp := os.Getenv("password"); tmp != "" {
		password = tmp
	}
	if tmp := os.Getenv("brokerID"); tmp != "" {
		brokerID = tmp
	}
	if tmp := os.Getenv("appID"); tmp != "" {
		appID = tmp
	}
	if tmp := os.Getenv("authCode"); tmp != "" {
		authCode = tmp
	}
	if tmp := os.Getenv("tradeFront"); tmp != "" {
		tradeFront = tmp
	}
	if tmp := os.Getenv("quoteFront"); tmp != "" {
		quoteFront = tmp
	}
	fmt.Println("tradeFront: ", tradeFront)
	fmt.Println("quoteFront: ", quoteFront)
	fmt.Printf("brokerID:%s\nuserID:%s\npassword:%s\nappID:%s\nauthCode:%s\n", brokerID, userID, password, appID, authCode)

	ctp.SetQuick() // quick 模式, 处理指定帐号
	t = ctp.NewTrade()
	q = ctp.NewQuote()
}

func releaseQuote() {
	q.Release()
	q = ctp.NewQuote()
}

func testQuote() {
	chConnected := make(chan bool)
	q.RegOnFrontConnected(func() {
		chConnected <- true
		fmt.Println("quote connected")
		q.ReqLogin(userID, password, brokerID)
	})
	q.RegOnRspUserLogin(func(login *goctp.RspUserLoginField, info *goctp.RspInfoField) {
		fmt.Printf("quote login: %+v\n", info)
	})
	q.RegOnTick(func(tick *goctp.TickField) {
		fmt.Printf("%+v\n", tick)
	})
	q.RegOnFrontDisConnected(func(reason int) {
		fmt.Println("quote disconected ", reason)
	})
	fmt.Println("connecting to quote " + quoteFront)
	q.ReqConnect(quoteFront)
	go func() {
		// 连接超时设置
		select {
		case <-chConnected:
		case <-time.After(10 * time.Second):
			fmt.Println("连接超时")
			releaseQuote()
		}
	}()
}

func releaseTrade() {
	t.Release()
	t = ctp.NewTrade()
}

func testTrade() {
	chConnected := make(chan bool)
	t.RegOnFrontConnected(func() {
		chConnected <- true
		fmt.Println("trade connected")
		go t.ReqLogin(userID, password, brokerID, appID, authCode)
	})

	t.RegOnRspUserLogin(func(login *goctp.RspUserLoginField, info *goctp.RspInfoField) {
		fmt.Printf("%+v\n", info)
		if info.ErrorID == 7 { // 未初始化
			go func() {
				time.Sleep(1 * time.Minute) // 一分钟试一次
				t.ReqLogin(userID, password, brokerID, appID, authCode)
			}()
		} else if info.ErrorID != 0 {
			go releaseTrade()
		} else {
			fmt.Printf("login: %+v\n", login)
			// fmt.Println("investors: ", t.Investors)
		}
	})

	t.RegOnRtnOrder(func(field *goctp.OrderField) {
		// fmt.Printf("OnRtnOrder: %+v\n", field)
	})
	t.RegOnRtnTrade(func(field *goctp.TradeField) {
		// fmt.Printf("OnRtnTrade: %+v\n", field)
	})
	t.RegOnRtnCancel(func(field *goctp.OrderField) {
		// fmt.Printf("OnRtnCancel: %+v\n", field)
	})
	t.RegOnErrRtnOrder(func(field *goctp.OrderField, info *goctp.RspInfoField) {
		// fmt.Printf("OnErrRtnOrder: %+v\n", field)
	})
	// 交易状态
	t.RegOnRtnInstrumentStatus(func(field *goctp.InstrumentStatus) {
		// fmt.Println(field)
	})
	// 断开
	t.RegOnFrontDisConnected(func(reason int) {
		fmt.Println("trade disconnected ", reason)
		if reason != 0 {
			releaseTrade()
		}
	})
	fmt.Println("connecting to trade " + tradeFront)
	t.ReqConnect(tradeFront)
	go func() {
		// 连接超时设置
		select {
		case <-chConnected:
		case <-time.After(10 * time.Second):
			fmt.Println("连接超时")
			releaseTrade()
		}
	}()
}

func run724() {
	// 应用启动
	testQuote()
	testTrade()
	tick := time.NewTicker(1 * time.Minute)
	for range tick.C {
		hhmm := time.Now().Local().Format("15:04")
		if t.IsLogin { // 收盘后退出
			isContinue := false
			t.InstrumentStatuss.Range(func(key, value interface{}) bool {
				if value.(*goctp.InstrumentStatus).InstrumentStatus == goctp.InstrumentStatusContinous {
					isContinue = true
					return false
				}
				return true
			})
			if time.Now().Local().Minute()%15 == 0 { // 15 分钟显示一次
				fmt.Println(hhmm, " 交易中: ", isContinue)
			}
			if !isContinue {
				hour := time.Now().Local().Hour()
				if hour <= 3 || hour == 15 { // 夜盘结束&当日收盘
					fmt.Println("release at ", time.Now().Local())
					releaseTrade()
				}
			}
		} else { // 定时连接
			if time.Now().Local().Minute()%15 == 0 { // 15 分钟显示一次
				fmt.Println(hhmm, " 接口关闭")
			}
			if hhmm == "08:40" || hhmm == "20:40" {
				fmt.Println("relogin at ", hhmm)
				testQuote()
				testTrade()
			}
		}
	}
}

func main() {
	go run724()

	for t == nil || !t.IsLogin {
		time.Sleep(1 * time.Second)
	}

	// 委托测试
	if true {
		// t.ReqOrderInsert("rb2210", goctp.DirectionBuy, goctp.OffsetFlagClose, 2850, 2)
		// t.ReqOrderInsertByUser("00200008", "rb2210", goctp.DirectionBuy, goctp.OffsetFlagOpen, 2850, 2)
	}
	// 合约
	if false {
		cnt := 0
		t.Instruments.Range(func(k, v interface{}) bool {
			cnt++
			return true
		})
		fmt.Println("instrument count:", cnt)
	}
	// 权益
	if false {
		fmt.Printf("Account: %+v\n", t.Account)
	}
	// 委托信息
	if false {
		t.Orders.Range(func(key, value interface{}) bool {
			fmt.Printf("%s: %+v\n", key, value)
			return true
		})
	}
	// 成交信息
	if false {
		t.Trades.Range(func(key, value interface{}) bool {
			fmt.Printf("%s: %+v\n", key, value)
			return true
		})
	}
	// 入金
	if false {
		t.RegOnRtnFromFutureToBank(func(field *goctp.TransferField) {
			fmt.Printf("入金: %+v\n", field)
		})
		t.ReqFutureToBank("", "", 30)
	}
	// 订阅合约
	if false {
		q.ReqSubscript("rb2210")
	}

	// 行情
	if false {
		time.Sleep(5 * time.Second)
		q.Ticks.Range(func(key, value interface{}) bool {
			fmt.Printf("%+v", value)
			return true
		})
	}
	// 权益
	if true {
		for { // 检查持仓/权益查询是否生效
			// for k, v := range t.UserAccounts {
			// 	fmt.Printf("%s 权益: %+v\n", k, v)
			// }
			fmt.Printf("%+v\n", t.UserAccounts["00200008"])
			time.Sleep(3 * time.Second)
		}
	}
	// 持仓
	if true {
		for k, v := range t.UserPositions {
			v.Range(func(key, value interface{}) bool {
				p := value.(*goctp.PositionField)
				fmt.Printf("%s || %s: %s: 昨:%d,今:%d,总: %d, 可: %d\n", k, key, p.InstrumentID, p.YdPosition, p.TodayPosition, p.Position, p.Position-p.ShortFrozen)
				return true
			})
		}
	}

	// 交易所状态
	if false {
		t.InstrumentStatuss.Range(func(key, value interface{}) bool {
			fmt.Printf("%+v\n", *value.(*goctp.InstrumentStatus))
			return true
		})
	}
	select {}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

haifengat

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值