package fix /* #cgo CFLAGS: -I./include #cgo LDFLAGS: -L./lib -lcfix #cgo linux LDFLAGS: -L/usr/lib -lquickfix -lsignalsync -lfix -lstdc++ -lboost_system -lboost_chrono -lboost_thread #include #include extern void message_callback_go(void* foo, void* trade, const void* msg, void* sid); void * message_callback (void *pfunc, AppTradeClient* trade, const Message* msg, SessionID* sid) { message_callback_go(pfunc, trade, msg, sid); return 0; } void * get_callback() { return message_callback; } */ import "C" import "fmt" import "unsafe" import "log" import "time" /* func PrintHello(strs []string) { ss := make([]*C.char, len(strs)) for i := 0; i < len(strs); i++ { ss[i] = C.CString(strs[i]) } C.PrintHello((**C.char)(unsafe.Pointer(&ss[0])), C.int(len(strs))) for i := 0; i < len(strs); i++ { C.free(unsafe.Pointer(ss[i])) } } */ type SessionSettings struct { obj *C.struct_SessionSettings } type IApplication interface { /// Notification of a session begin created onCreate(*AppTradeClient, *SessionID) /// Notification of a session successfully logging on onLogon(*AppTradeClient, *SessionID) /// Notification of a session logging off or disconnecting onLogout(*AppTradeClient, *SessionID) /// Notification of admin message being sent to target toAdmin(*AppTradeClient, *Message, *SessionID) /// Notification of app message being sent to target toApp(*AppTradeClient, *Message, *SessionID) /// Notification of admin message being received from target fromAdmin(*AppTradeClient, *Message, *SessionID) /// Notification of app message being received from target fromApp(*AppTradeClient, *Message, *SessionID) } type AppTradeClient struct { obj *C.struct_AppTradeClient app IApplication iapp *Application setting *SessionSettings onCreate func(unsafe.Pointer, unsafe.Pointer) /// Notification of a session successfully logging on onLogon func(unsafe.Pointer, unsafe.Pointer) /// Notification of a session logging off or disconnecting onLogout func(unsafe.Pointer, unsafe.Pointer) /// Notification of admin message being sent to target toAdmin func(unsafe.Pointer, unsafe.Pointer, unsafe.Pointer) /// Notification of app message being sent to target toApp func(unsafe.Pointer, unsafe.Pointer, unsafe.Pointer) /// Notification of admin message being received from target fromAdmin func(unsafe.Pointer, unsafe.Pointer, unsafe.Pointer) /// Notification of app message being received from target fromApp func(unsafe.Pointer, unsafe.Pointer, unsafe.Pointer) } type AppBase struct { } /// Notification of a session begin created func (app *AppBase) onCreate(tc *AppTradeClient, sid *SessionID) { log.Println("onCreate go") } /// Notification of a session successfully logging on func (app *AppBase) onLogon(tc *AppTradeClient, sid *SessionID) { log.Println("onLogon go") } /// Notification of a session logging off or disconnecting func (app *AppBase) onLogout(tc *AppTradeClient, sid *SessionID) { log.Println("onLogout go") } /// Notification of admin message being sent to target func (app *AppBase) toAdmin(tc *AppTradeClient, msg *Message, sid *SessionID) { log.Println("toAdmin go", msg.ToStr()) } /// Notification of app message being sent to target func (app *AppBase) toApp(tc *AppTradeClient, msg *Message, sid *SessionID) { log.Println("toApp go", msg.ToStr()) } /// Notification of admin message being received from target func (app *AppBase) fromAdmin(tc *AppTradeClient, msg *Message, sid *SessionID) { log.Println("fromAdmin go", msg.ToStr()) } /// Notification of app message being received from target func (app *AppBase) fromApp(tc *AppTradeClient, msg *Message, sid *SessionID) { log.Println("fromApp go", msg.ToStr()) } type Message struct { obj *C.struct_Message } type SessionID struct { obj *C.struct_SessionID } type Dictionary struct { obj *C.struct_Dictionary } type Application struct { obj *C.IApplication } const MAX_BID_ASK_COUNT = 25 type TickFull struct { AskPrice [MAX_BID_ASK_COUNT]float64 BidPrice [MAX_BID_ASK_COUNT]float64 AskVolume [MAX_BID_ASK_COUNT]float64 BidVolume [MAX_BID_ASK_COUNT]float64 Symbol [8]byte Time int32 Millisecond int32 AskCount int32 BidCount int32 } type StockInfo struct { Symbol [15]byte Position int32 SecurityExchange [10]byte } type orderInfo struct { OrderID [32]byte //Unique identifier for Order as assigned by exchange SecondaryExecID [32]byte ClOrdID [32]byte //Client side order identifier OrigClOrdID [32]byte OrdStatusReqID [32]byte ExecID [32]byte //Execution ID for this fill. Account [16]byte //Account ID of the current logged in LMAX member SecurityID [8]byte AvgPx float64 //Calculated average price of all fills on this order. CumQty float64 //Contains the cumulated traded quantity for the order through its life. LastPx float64 //Price of this fill LastQty float64 // OrderQty float64 //Number of contracts submitted by the client LeavesQty float64 //成交手数 Price float64 //Price per contract Text unsafe.Pointer OrdRejReason int TransactTime int //Time of execution/order creation Millisecond int SecurityIDSource [2]byte TimeInForce byte OrdType byte OrdStatus byte Side byte //1=BUY ,2=SELL ExecType byte } func NewSessionSettings(file string) (*SessionSettings, error) { cstr := C.CString(file) defer C.free(unsafe.Pointer(cstr)) c := C.NewSessionSettings(cstr) if c == nil { return nil, fmt.Errorf("create new NewSessionSettings object error.") } return &SessionSettings{obj: c}, nil } func (c *SessionSettings) Free() { if c.obj != nil { C.FreeSessionSettings(c.obj) c.obj = nil } } func (ss *SessionSettings) Get(sid *SessionID) *Dictionary { dict := &Dictionary{} dict.obj = C.SessionSettingsGet(ss.obj, sid.obj) return dict } func (dict *Dictionary) Has(find string) bool { cstr := C.CString(find) defer C.free(unsafe.Pointer(cstr)) ret := C.DictionaryHas(dict.obj, cstr) if int(ret) == 1 { return true } return false } func (dict *Dictionary) GetString(find string) string { cstr := C.CString(find) defer C.free(unsafe.Pointer(cstr)) ret := C.DictionaryGetString(dict.obj, cstr) return C.GoString(ret) } func (dict *Dictionary) Free() { if dict.obj != nil { C.FreeDictionary(dict.obj) dict.obj = nil } } func WarpSessionID(sid unsafe.Pointer) *SessionID { sessionId := &SessionID{} sessionId.obj = C.WarpSessionID(sid) return sessionId } func WarpMessage(msg unsafe.Pointer) *Message { message := &Message{} message.obj = C.WarpMessage(msg) return message } func (msg *Message) SetField(field int, value string) { cstr := C.CString(value) defer C.free(unsafe.Pointer(cstr)) C.MessageSetField(msg.obj, C.int(field), cstr) } func (msg *Message) Send() int { return int(C.MessageSend(msg.obj)) } func (msg *Message) ToStr() string { cstr := C.MessageToStr(msg.obj) if cstr == nil { return "" } defer C.Free(unsafe.Pointer(cstr)) return C.GoString(cstr) } func NewAppTradeClient(app IApplication, setting *SessionSettings) (*AppTradeClient, error) { tradeclient := &AppTradeClient{} tradeclient.app = app tradeclient.onCreate = func(trade unsafe.Pointer, sid unsafe.Pointer) { tradeclient.app.onCreate(tradeclient, WarpSessionID(sid)) } tradeclient.onLogon = func(trade unsafe.Pointer, sid unsafe.Pointer) { tradeclient.app.onLogon(tradeclient, WarpSessionID(sid)) } tradeclient.onLogout = func(trade unsafe.Pointer, sid unsafe.Pointer) { tradeclient.app.onLogout(tradeclient, WarpSessionID(sid)) } tradeclient.toAdmin = func(trade unsafe.Pointer, msg unsafe.Pointer, sid unsafe.Pointer) { tradeclient.app.toAdmin(tradeclient, WarpMessage(msg), WarpSessionID(sid)) } tradeclient.fromAdmin = func(trade unsafe.Pointer, msg unsafe.Pointer, sid unsafe.Pointer) { tradeclient.app.fromAdmin(tradeclient, WarpMessage(msg), WarpSessionID(sid)) } tradeclient.toApp = func(trade unsafe.Pointer, msg unsafe.Pointer, sid unsafe.Pointer) { tradeclient.app.toApp(tradeclient, WarpMessage(msg), WarpSessionID(sid)) } tradeclient.fromApp = func(trade unsafe.Pointer, msg unsafe.Pointer, sid unsafe.Pointer) { tradeclient.app.fromApp(tradeclient, WarpMessage(msg), WarpSessionID(sid)) } iapp := NewApplication(tradeclient) tradeclient.iapp = iapp tradeclient.setting = setting t := time.Now() tradeclient.obj = C.NewAppTradeClient(iapp.obj, setting.obj) log.Print(time.Now().Sub(t)) if tradeclient.obj == nil { return nil, fmt.Errorf("NewAppTradeClient error.") } return tradeclient, nil } func NewApplication(tc *AppTradeClient) *Application { app := &Application{} app.obj = C.NewCBIApplication(C.get_callback(), unsafe.Pointer(&tc.onCreate), unsafe.Pointer(&tc.onLogon), unsafe.Pointer(&tc.onLogout), unsafe.Pointer(&tc.toAdmin), unsafe.Pointer(&tc.toApp), unsafe.Pointer(&tc.fromAdmin), unsafe.Pointer(&tc.fromApp)) return app } func (app *Application) Free() { if app.obj != nil { C.FreeIApplication(app.obj) app.obj = nil } } func (tradeclient *AppTradeClient) Free() { tradeclient.setting.Free() tradeclient.iapp.Free() if tradeclient.obj != nil { C.FreeAppTradeClient(tradeclient.obj) tradeclient.obj = nil } } func (tradeclient *AppTradeClient) Start() { C.AppTradeClientStart(tradeclient.obj) } func (tradeclient *AppTradeClient) Stop() { C.AppTradeClientStop(tradeclient.obj) } func (tradeclient *AppTradeClient) Run() int { ret := C.AppTradeClientRun(tradeclient.obj) return int(ret) } func (tradeclient *AppTradeClient) SessionID() *SessionID { sid := C.AppTradeClientSessionID(tradeclient.obj) return WarpSessionID(unsafe.Pointer(sid)) } func (tradeclient *AppTradeClient) SenderCompID() string { cstr := C.AppTradeClientSenderCompID(tradeclient.obj) return C.GoString(cstr) } func (tradeclient *AppTradeClient) TargetCompID() string { cstr := C.AppTradeClientTargetCompID(tradeclient.obj) return C.GoString(cstr) } func (tradeclient *AppTradeClient) ClOrdID() string { cstr := C.AppTradeClientClOrdID(tradeclient.obj) return C.GoString(cstr) } func GetMarketData(msg *Message) (*TickFull, bool) { tick := &TickFull{} ret := C.GetMarketData(msg.obj, (*C.TickFull)(unsafe.Pointer(tick))) if int(ret) == 1 { return tick, true } return tick, false } func (tradeclient *AppTradeClient) OrigClOrdID(msg *Message) string { cstr := C.AppTradeClientOrigClOrdID(tradeclient.obj, msg.obj) return C.GoString(cstr) } func (tradeclient *AppTradeClient) SendOrder(bookId string, clordId string, handInst byte, side byte, orderType byte, qty float64, price float64, account string, securitytype string, securityexchange string, currency string) bool { cbookId := C.CString(bookId) defer C.free(unsafe.Pointer(cbookId)) cclordId := C.CString(clordId) defer C.free(unsafe.Pointer(cclordId)) caccount := C.CString(account) defer C.free(unsafe.Pointer(caccount)) csecuritytype := C.CString(securitytype) defer C.free(unsafe.Pointer(csecuritytype)) csecurityexchange := C.CString(securityexchange) defer C.free(unsafe.Pointer(csecurityexchange)) ccurrency := C.CString(currency) defer C.free(unsafe.Pointer(ccurrency)) ret := C.AppTradeClientSendOrder(tradeclient.obj, cbookId, cclordId, C.char(side), C.char(orderType), C.double(qty), C.double(price), caccount) if int(ret) == 1 { return true } return false } func (tradeclient *AppTradeClient) CancleOrder(bookId string, origClordid string, clordId string, side byte, qty float64, account string, securitytype string, orderid string) bool { cbookId := C.CString(bookId) defer C.free(unsafe.Pointer(cbookId)) cclordId := C.CString(clordId) defer C.free(unsafe.Pointer(cclordId)) corigClordid := C.CString(origClordid) defer C.free(unsafe.Pointer(corigClordid)) caccount := C.CString(account) defer C.free(unsafe.Pointer(caccount)) csecuritytype := C.CString(securitytype) defer C.free(unsafe.Pointer(csecuritytype)) corderid := C.CString(orderid) defer C.free(unsafe.Pointer(corderid)) ret := C.AppTradeClientCancelOrder(tradeclient.obj, cbookId, corigClordid, cclordId, C.char(side), caccount, corderid) if int(ret) == 1 { return true } return false } /* func (tradeclient *AppTradeClient) StatusOrder(bookId string, clordId string, side byte, account string, securitytype string, orderid string) bool { cbookId := C.CString(bookId) defer C.free(unsafe.Pointer(cbookId)) cclordId := C.CString(clordId) defer C.free(unsafe.Pointer(cclordId)) caccount := C.CString(account) defer C.free(unsafe.Pointer(caccount)) csecuritytype := C.CString(securitytype) defer C.free(unsafe.Pointer(csecuritytype)) corderid := C.CString(orderid) defer C.free(unsafe.Pointer(corderid)) ret := C.AppTradeClientOrderStatus(tradeclient.obj, cbookId, cclordId, C.char(side), caccount, csecuritytype, corderid) if int(ret) == 1 { return true } return false } */ func (tradeclient *AppTradeClient) CollectiveOrder(clordId string, handlInst byte, ordertype byte, sidestr string, symbolstr string, orderQtyStr string, priceStr string, securityExchangeStr string, currentStr string, account string, securityTypeStr string, accountStr string, entrustNum int) bool { cclordId := C.CString(clordId) defer C.free(unsafe.Pointer(cclordId)) csidestr := C.CString(sidestr) defer C.free(unsafe.Pointer(csidestr)) csymbolstr := C.CString(symbolstr) defer C.free(unsafe.Pointer(csymbolstr)) corderQtyStr := C.CString(orderQtyStr) defer C.free(unsafe.Pointer(corderQtyStr)) cpriceStr := C.CString(priceStr) defer C.free(unsafe.Pointer(cpriceStr)) csecurityExchangeStr := C.CString(securityExchangeStr) defer C.free(unsafe.Pointer(csecurityExchangeStr)) ccurrentStr := C.CString(currentStr) defer C.free(unsafe.Pointer(ccurrentStr)) caccount := C.CString(account) defer C.free(unsafe.Pointer(caccount)) csecurityTypeStr := C.CString(securityTypeStr) defer C.free(unsafe.Pointer(csecurityTypeStr)) caccountStr := C.CString(accountStr) defer C.free(unsafe.Pointer(caccountStr)) ret := C.AppTradeClientCollectiveOrder(tradeclient.obj, cclordId, C.char(handlInst), C.char(ordertype), csidestr, csymbolstr, corderQtyStr, cpriceStr, csecurityExchangeStr, ccurrentStr, caccount, csecurityTypeStr, caccountStr, C.int(entrustNum)) if int(ret) == 1 { return true } return false } func (tradeclient *AppTradeClient) CollectiveOrderCancel(clordId string, entrustNum int, entrustNoStr string, securityExchangeStr string, currencyStr string, account string) bool { cclordId := C.CString(clordId) defer C.free(unsafe.Pointer(cclordId)) centrustNoStr := C.CString(entrustNoStr) defer C.free(unsafe.Pointer(centrustNoStr)) csecurityExchangeStr := C.CString(securityExchangeStr) defer C.free(unsafe.Pointer(csecurityExchangeStr)) ccurrencyStr := C.CString(currencyStr) defer C.free(unsafe.Pointer(ccurrencyStr)) caccount := C.CString(account) defer C.free(unsafe.Pointer(caccount)) ret := C.AppTradeClientCollectiveOrderCancel(tradeclient.obj, cclordId, C.int(entrustNum), centrustNoStr, csecurityExchangeStr, ccurrencyStr, caccount) if int(ret) == 1 { return true } return false } func (tradeclient *AppTradeClient) CollectiveOrderStatus(entrustNum int, entrustNoStr string, account string) bool { centrustNoStr := C.CString(entrustNoStr) defer C.free(unsafe.Pointer(centrustNoStr)) caccount := C.CString(account) defer C.free(unsafe.Pointer(caccount)) ret := C.AppTradeClientCollectiveOrderStatus(tradeclient.obj, C.int(entrustNum), centrustNoStr, caccount) if int(ret) == 1 { return true } return false } func (tradeclient *AppTradeClient) BatchOrder(clordId string, handlInst byte, ordertype byte, symbolstr []string, sidestr []string, orderQtyStr []string, priceStr []string, securityExchangeStr []string, currentStr []string, securityTypeStr []string, account string, num int) bool { cclordId := C.CString(clordId) defer C.free(unsafe.Pointer(cclordId)) psymbolstr := make([]*C.char, len(symbolstr)) for i := range symbolstr { psymbolstr[i] = C.CString(symbolstr[i]) defer C.free(unsafe.Pointer(psymbolstr[i])) } psidestr := make([]*C.char, len(sidestr)) for i := range sidestr { psidestr[i] = C.CString(sidestr[i]) defer C.free(unsafe.Pointer(psidestr[i])) } pcorderQtyStr := make([]*C.char, len(orderQtyStr)) for i := range orderQtyStr { pcorderQtyStr[i] = C.CString(orderQtyStr[i]) defer C.free(unsafe.Pointer(pcorderQtyStr[i])) } ppriceStr := make([]*C.char, len(priceStr)) for i := range priceStr { ppriceStr[i] = C.CString(priceStr[i]) defer C.free(unsafe.Pointer(ppriceStr[i])) } pcsecurityExchangeStr := make([]*C.char, len(securityExchangeStr)) for i := range securityExchangeStr { pcsecurityExchangeStr[i] = C.CString(securityExchangeStr[i]) defer C.free(unsafe.Pointer(pcsecurityExchangeStr[i])) } pcurrentStr := make([]*C.char, len(currentStr)) for i := range currentStr { pcurrentStr[i] = C.CString(currentStr[i]) defer C.free(unsafe.Pointer(pcurrentStr[i])) } psecurityTypeStr := make([]*C.char, len(securityTypeStr)) for i := range securityTypeStr { psecurityTypeStr[i] = C.CString(securityTypeStr[i]) defer C.free(unsafe.Pointer(psecurityTypeStr[i])) } caccount := C.CString(account) defer C.free(unsafe.Pointer(caccount)) ret := C.AppTradeClientBatchOrder(tradeclient.obj, cclordId, C.char(handlInst), C.char(ordertype), (**C.char)(unsafe.Pointer(&psymbolstr[0])), (**C.char)(unsafe.Pointer(&psidestr[0])), (**C.char)(unsafe.Pointer(&pcorderQtyStr[0])), (**C.char)(unsafe.Pointer(&ppriceStr[0])), (**C.char)(unsafe.Pointer(&pcsecurityExchangeStr[0])), (**C.char)(unsafe.Pointer(&pcurrentStr[0])), (**C.char)(unsafe.Pointer(&psecurityTypeStr[0])), caccount, C.int(num)) if int(ret) == 1 { return true } return false } func (tradeclient *AppTradeClient) RequestForPositions(posReqID string, posReqType int, account string, accountType int) bool { cposReqID := C.CString(posReqID) defer C.free(unsafe.Pointer(cposReqID)) caccount := C.CString(account) defer C.free(unsafe.Pointer(caccount)) ret := C.AppTradeClientRequestForPositions(tradeclient.obj, cposReqID, C.int(posReqType), caccount, C.int(accountType)) if int(ret) == 1 { return true } return false } func (tradeclient *AppTradeClient) TradeCaptureReportRequest(reqId string, reqType int, subType byte) bool { creqId := C.CString(reqId) defer C.free(unsafe.Pointer(creqId)) ret := C.AppTradeClientTradeCaptureReportRequest(tradeclient.obj, creqId, C.int(reqType), C.char(subType)) if int(ret) == 1 { return true } return false } func (tradeclient *AppTradeClient) MarketData(bookId string, subscriptionRequestType byte) bool { cbookId := C.CString(bookId) defer C.free(unsafe.Pointer(cbookId)) //csecurityExchange := C.CString(securityExchange) //defer C.free(unsafe.Pointer(csecurityExchange)) ret := C.AppTradeClientMarketData(tradeclient.obj, cbookId, C.char(subscriptionRequestType)) if int(ret) == 1 { return true } return false } func GetMsgType(msg *Message) (string, bool) { var TypeValue [32]byte ret := C.GetMsgType(msg.obj, (*C.char)(unsafe.Pointer(&TypeValue[0]))) if int(ret) == 1 { return cstring(TypeValue[:]), true } return "", false } func GetAccountStockInfo(msg *Message) (*StockInfo, int, bool) { stockinfo := &StockInfo{} nLastRptRequested := 0 ret := C.GetAccountStockInfo(msg.obj, (*C.StockInfo)(unsafe.Pointer(stockinfo)), (*C.int)(unsafe.Pointer(&nLastRptRequested))) if int(ret) == 1 { return stockinfo, nLastRptRequested, true } return nil, 0, false } func GetOrderStatus(msg *Message) (*OrderStatus, bool) { info := &orderInfo{} ret := C.GetOrderInfo(msg.obj, (*C.OrderInfo)(unsafe.Pointer(info))) if int(ret) == 1 { return formatOrderInfo(info), true } return nil, false } func formatOrderInfo(info *orderInfo) *OrderStatus { status := &OrderStatus{} status.OrderID = cstring(info.OrderID[:]) status.SecondaryExecID = cstring(info.SecondaryExecID[:]) status.ClOrdID = cstring(info.ClOrdID[:]) status.OrigClOrdID = cstring(info.OrigClOrdID[:]) status.OrdStatusReqID = cstring(info.OrdStatusReqID[:]) status.ExecID = cstring(info.ExecID[:]) status.Account = cstring(info.Account[:]) status.SecurityID = cstring(info.SecurityID[:]) status.SecurityIDSource = cstring(info.SecurityIDSource[:]) status.Text = C.GoString((*C.char)(info.Text)) C.Free(info.Text) //复制其他的字段 status.ExecType = info.ExecType status.OrdStatus = info.OrdStatus status.OrdRejReason = info.OrdRejReason status.Side = info.Side status.OrdType = info.OrdType status.Price = info.Price //status.TimeInForce = info.TimeInForce status.LastQty = info.LastQty status.LastPx = info.LastPx status.LeavesQty = info.LeavesQty status.CumQty = info.CumQty status.AvgPx = info.AvgPx return status } func cstring(s []byte) string { for i := range s { if s[i] == 0 { return string(s[0:i]) } } return string(s) }