diff --git a/cmd/cmd.go b/cmd/cmd.go index 24f30be..07ac9f6 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -17,6 +17,7 @@ package cmd import ( "github.com/quickfixgo/examples/cmd/executor" + "github.com/quickfixgo/examples/cmd/loadtest" "github.com/quickfixgo/examples/cmd/ordermatch" "github.com/quickfixgo/examples/cmd/tradeclient" "github.com/quickfixgo/examples/version" @@ -45,6 +46,7 @@ func Execute() error { c.AddCommand(executor.Cmd) c.AddCommand(ordermatch.Cmd) c.AddCommand(tradeclient.Cmd) + c.AddCommand(loadtest.Cmd) c.Flags().BoolVarP(&versionF, "version", "v", false, "show the version and exit") return c.Execute() } diff --git a/cmd/loadtest/loadtest.go b/cmd/loadtest/loadtest.go new file mode 100644 index 0000000..a726f7a --- /dev/null +++ b/cmd/loadtest/loadtest.go @@ -0,0 +1,43 @@ +package loadtest + +import ( + "fmt" + "time" + + "github.com/spf13/cobra" +) + +var ( + // Cmd is the load test command. + Cmd = &cobra.Command{ + Use: "loadtest", + Short: "Perform load testing by sending FIX orders", + Long: "Load testing tool for sending multiple FIX orders at a configurable rate.", + Example: "qf loadtest --orders 100 --rate 10", + RunE: execute, + } + + orderCount int + rate int +) + +func init() { + Cmd.Flags().IntVarP(&orderCount, "orders", "o", 100, "Number of orders to send") + Cmd.Flags().IntVarP(&rate, "rate", "r", 10, "Orders per second") +} + +func execute(cmd *cobra.Command, args []string) error { + fmt.Printf("Starting load test: %d orders at %d orders/second\n", orderCount, rate) + + for i := 0; i < orderCount; i++ { + sendOrder(i) // Replace this with actual order sending logic + time.Sleep(time.Second / time.Duration(rate)) // Control the rate + } + + return nil +} + +// sendOrder is a stub for sending an order. Replace with actual implementation. +func sendOrder(orderID int) { + fmt.Printf("Order %d sent\n", orderID) +} diff --git a/cmd/ordermatch/ordermatch.go b/cmd/ordermatch/ordermatch.go index c1714fb..42da750 100644 --- a/cmd/ordermatch/ordermatch.go +++ b/cmd/ordermatch/ordermatch.go @@ -25,15 +25,19 @@ import ( "path" "strconv" "syscall" + "time" "github.com/quickfixgo/enum" "github.com/quickfixgo/examples/cmd/ordermatch/internal" "github.com/quickfixgo/examples/cmd/utils" "github.com/quickfixgo/field" - "github.com/quickfixgo/fix42/executionreport" - "github.com/quickfixgo/fix42/marketdatarequest" - "github.com/quickfixgo/fix42/newordersingle" - "github.com/quickfixgo/fix42/ordercancelrequest" + "github.com/quickfixgo/fix44/executionreport" + "github.com/quickfixgo/fix44/marketdatarequest" + "github.com/quickfixgo/fix44/marketdatasnapshotfullrefresh" + + "github.com/quickfixgo/fix44/newordersingle" + "github.com/quickfixgo/fix44/ordercancelrequest" + "github.com/shopspring/decimal" "github.com/spf13/cobra" "github.com/quickfixgo/quickfix" @@ -77,11 +81,13 @@ func (a Application) ToApp(msg *quickfix.Message, sessionID quickfix.SessionID) // FromAdmin implemented as part of Application interface func (a Application) FromAdmin(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError { + fmt.Printf("FromAdmin ###########>%+v\n", msg) return nil } // FromApp implemented as part of Application interface, uses Router on incoming application messages func (a *Application) FromApp(msg *quickfix.Message, sessionID quickfix.SessionID) (reject quickfix.MessageRejectError) { + fmt.Printf("FromApp ###########>\n") return a.Route(msg, sessionID) } @@ -176,7 +182,49 @@ func (a *Application) onOrderCancelRequest(msg ordercancelrequest.OrderCancelReq func (a *Application) onMarketDataRequest(msg marketdatarequest.MarketDataRequest, sessionID quickfix.SessionID) (err quickfix.MessageRejectError) { fmt.Printf("%+v\n", msg) - return + marketdatafullrefresh := marketdatasnapshotfullrefresh.New() + + marketdatafullrefresh.SetSymbol("BTC/USD") + marketdatafullrefresh.SetMDReqID("MDReq1") + marketdatafullrefresh.SetProduct(enum.Product_CURRENCY) + + noMDEntriesRptGrp := marketdatasnapshotfullrefresh.NewNoMDEntriesRepeatingGroup() + + median_px := 68000.0 + for i := 0; i < 5; i++ { + sz := decimal.NewFromInt(int64(i + 1)) + noMDEntries0 := noMDEntriesRptGrp.Add() + noMDEntries0.SetMDEntryType(enum.MDEntryType_BID) + var bid_px = median_px - (float64(i+1) * 5.0) + p0 := decimal.NewFromFloat(bid_px) + noMDEntries0.SetMDEntryPx(p0, 5) + noMDEntries0.SetMDEntrySize(sz, 2) + + noMDEntries1 := noMDEntriesRptGrp.Add() + noMDEntries1.SetMDEntryType(enum.MDEntryType_OFFER) + var off_px = median_px + (float64(i+1) * 5.0) + p1 := decimal.NewFromFloat(off_px) + noMDEntries1.SetMDEntryPx(p1, 5) + noMDEntries1.SetMDEntrySize(sz, 2) + } + + marketdatafullrefresh.SetNoMDEntries(noMDEntriesRptGrp) + + marketdatafullrefresh.Header.SetTargetCompID("TW") + marketdatafullrefresh.Header.SetSenderCompID("ISLD") + + sendErr := quickfix.Send(marketdatafullrefresh) + + if sendErr != nil { + fmt.Println(sendErr) + } + + errUpdate := StartUpdateRefresh() + if errUpdate != nil { + fmt.Printf("failed to start update refresher!!") + } + + return nil } func (a *Application) acceptOrder(order internal.Order) { @@ -204,10 +252,10 @@ func (a *Application) updateOrder(order internal.Order, status enum.OrdStatus) { execReport := executionreport.New( field.NewOrderID(order.ClOrdID), field.NewExecID(a.genExecID()), - field.NewExecTransType(enum.ExecTransType_NEW), + //field.NewExecTransType(enum.ExecTransType_NEW), field.NewExecType(enum.ExecType(status)), field.NewOrdStatus(status), - field.NewSymbol(order.Symbol), + //field.NewSymbol(order.Symbol), field.NewSide(order.Side), field.NewLeavesQty(order.OpenQuantity(), 2), field.NewCumQty(order.ExecutedQuantity, 2), @@ -215,10 +263,11 @@ func (a *Application) updateOrder(order internal.Order, status enum.OrdStatus) { ) execReport.SetOrderQty(order.Quantity, 2) execReport.SetClOrdID(order.ClOrdID) + execReport.SetSymbol(order.Symbol) switch status { case enum.OrdStatus_FILLED, enum.OrdStatus_PARTIALLY_FILLED: - execReport.SetLastShares(order.LastExecutedQuantity, 2) + execReport.SetLastQty(order.LastExecutedQuantity, 2) execReport.SetLastPx(order.LastExecutedPrice, 2) } @@ -232,6 +281,56 @@ func (a *Application) updateOrder(order internal.Order, status enum.OrdStatus) { } +func StartUpdateRefresh() (err error) { + fmt.Printf("StartUpdateRefresh==>") + go func() { + for j := 0; ; j++ { + + time.Sleep(20 * time.Second) + + marketdatafullrefresh := marketdatasnapshotfullrefresh.New() + + marketdatafullrefresh.SetSymbol("BTC/USD") + marketdatafullrefresh.SetMDReqID("MDReq" + fmt.Sprint(j)) + marketdatafullrefresh.SetProduct(enum.Product_CURRENCY) + + noMDEntriesRptGrp := marketdatasnapshotfullrefresh.NewNoMDEntriesRepeatingGroup() + + median_px := 68000.0 + float64(j*2) + for i := 0; i < 5; i++ { + sz := decimal.NewFromInt(int64(i + 1)) + sprd := float64(i+1) * 5.0 + + noMDEntries0 := noMDEntriesRptGrp.Add() + noMDEntries0.SetMDEntryType(enum.MDEntryType_BID) + var bid_px = median_px - sprd + p0 := decimal.NewFromFloat(bid_px) + noMDEntries0.SetMDEntryPx(p0, 5) + noMDEntries0.SetMDEntrySize(sz, 2) + + noMDEntries1 := noMDEntriesRptGrp.Add() + noMDEntries1.SetMDEntryType(enum.MDEntryType_OFFER) + var off_px = median_px + sprd + p1 := decimal.NewFromFloat(off_px) + noMDEntries1.SetMDEntryPx(p1, 5) + noMDEntries1.SetMDEntrySize(sz, 2) + } + + marketdatafullrefresh.SetNoMDEntries(noMDEntriesRptGrp) + + marketdatafullrefresh.Header.SetTargetCompID("TW") + marketdatafullrefresh.Header.SetSenderCompID("ISLD") + + sendErr := quickfix.Send(marketdatafullrefresh) + + if sendErr != nil { + fmt.Println(sendErr) + } + } + }() + return nil +} + const ( usage = "ordermatch" short = "Start an order matching (FIX acceptor) service" diff --git a/cmd/tradeclient/internal/console.go b/cmd/tradeclient/internal/console.go index 8db8de1..d80acad 100644 --- a/cmd/tradeclient/internal/console.go +++ b/cmd/tradeclient/internal/console.go @@ -18,6 +18,7 @@ package internal import ( "bufio" "fmt" + "math/rand" "time" "github.com/quickfixgo/enum" @@ -88,6 +89,7 @@ func queryFieldChoices(fieldName string, choices []string, values []string) stri } func QueryAction() (string, error) { + fmt.Println() fmt.Println("1) Enter Order") fmt.Println("2) Cancel Order") @@ -100,36 +102,39 @@ func QueryAction() (string, error) { } func queryVersion() (string, error) { - fmt.Println() - fmt.Println("1) FIX.4.0") - fmt.Println("2) FIX.4.1") - fmt.Println("3) FIX.4.2") - fmt.Println("4) FIX.4.3") - fmt.Println("5) FIX.4.4") - fmt.Println("6) FIXT.1.1 (FIX.5.0)") - fmt.Print("BeginString: ") - - scanner := bufio.NewScanner(os.Stdin) - if !scanner.Scan() { - return "", scanner.Err() - } + /* + fmt.Println() + fmt.Println("1) FIX.4.0") + fmt.Println("2) FIX.4.1") + fmt.Println("3) FIX.4.2") + fmt.Println("4) FIX.4.3") + fmt.Println("5) FIX.4.4") + fmt.Println("6) FIXT.1.1 (FIX.5.0)") + fmt.Print("BeginString: ") + + scanner := bufio.NewScanner(os.Stdin) + if !scanner.Scan() { + return "", scanner.Err() + } - switch scanner.Text() { - case "1": - return quickfix.BeginStringFIX40, nil - case "2": - return quickfix.BeginStringFIX41, nil - case "3": - return quickfix.BeginStringFIX42, nil - case "4": - return quickfix.BeginStringFIX43, nil - case "5": - return quickfix.BeginStringFIX44, nil - case "6": - return quickfix.BeginStringFIXT11, nil - } + switch scanner.Text() { + case "1": + return quickfix.BeginStringFIX40, nil + case "2": + return quickfix.BeginStringFIX41, nil + case "3": + return quickfix.BeginStringFIX42, nil + case "4": + return quickfix.BeginStringFIX43, nil + case "5": + return quickfix.BeginStringFIX44, nil + case "6": + return quickfix.BeginStringFIXT11, nil + } - return "", fmt.Errorf("unknown BeginString choice: %v", scanner.Text()) + return "", fmt.Errorf("unknown BeginString choice: %v", scanner.Text()) + */ + return quickfix.BeginStringFIX44, nil } func queryClOrdID() field.ClOrdIDField { @@ -245,13 +250,24 @@ type header interface { } func queryHeader(h header) { - h.Set(querySenderCompID()) - h.Set(queryTargetCompID()) - if ok := queryConfirm("Use a TargetSubID"); !ok { - return - } + /* + h.Set(querySenderCompID()) + h.Set(queryTargetCompID()) + if ok := queryConfirm("Use a TargetSubID"); !ok { + return + } + + h.Set(queryTargetSubID()) + */ + //h.Set(field.NewSenderCompID(senderCompId)) + //h.Set(field.NewTargetCompID(targetCompId)) + h.Set(field.NewSenderCompID("CLIENT1_Order")) + h.Set(field.NewTargetCompID("A")) +} - h.Set(queryTargetSubID()) +func setHeader(h header, senderCompId string, targetCompId string) { + h.Set(field.NewSenderCompID(senderCompId)) + h.Set(field.NewTargetCompID(targetCompId)) } func queryNewOrderSingle40() fix40nos.NewOrderSingle { @@ -269,7 +285,7 @@ func queryNewOrderSingle40() fix40nos.NewOrderSingle { } order.Set(queryTimeInForce()) - queryHeader(order.Header.Header) + queryHeader(order.Header) return order } @@ -340,26 +356,32 @@ func queryNewOrderSingle43() (msg *quickfix.Message) { return } -func queryNewOrderSingle44() (msg *quickfix.Message) { - var ordType field.OrdTypeField - order := fix44nos.New(queryClOrdID(), querySide(), field.NewTransactTime(time.Now()), queryOrdType(&ordType)) +func queryNewOrderSingle44(senderCompId, targetCompId, side, symbol, qty, price string) (msg *quickfix.Message) { + var ordType = enum.OrdType_LIMIT + order := fix44nos.New(field.NewClOrdID(strconv.Itoa(time.Now().Nanosecond())), + field.NewSide(enum.Side(side)), + field.NewTransactTime(time.Now()), + field.NewOrdType(ordType)) order.SetHandlInst("1") - order.Set(querySymbol()) - order.Set(queryOrderQty()) - - switch ordType.Value() { - case enum.OrdType_LIMIT, enum.OrdType_STOP_LIMIT: - order.Set(queryPrice()) - } - - switch ordType.Value() { - case enum.OrdType_STOP, enum.OrdType_STOP_LIMIT: + order.Set(field.NewSymbol(symbol)) + ordqty, _ := decimal.NewFromString(qty) + order.Set(field.NewOrderQty(ordqty, 4)) + order.Set(field.NewTimeInForce(enum.TimeInForce_FILL_OR_KILL)) + + switch ordType { + case enum.OrdType_LIMIT: + px, _ := decimal.NewFromString(price) + order.Set(field.NewPrice(px, 5)) + case enum.OrdType_STOP_LIMIT: + px, _ := decimal.NewFromString("3000.00") + order.Set(field.NewPrice(px, 5)) order.Set(queryStopPx()) + case enum.OrdType_STOP: + } - order.Set(queryTimeInForce()) msg = order.ToMessage() - queryHeader(&msg.Header) + setHeader(&msg.Header, senderCompId, targetCompId) return } @@ -475,21 +497,25 @@ func queryMarketDataRequest43() fix43mdr.MarketDataRequest { return request } -func queryMarketDataRequest44() fix44mdr.MarketDataRequest { - request := fix44mdr.New(field.NewMDReqID("MARKETDATAID"), - field.NewSubscriptionRequestType(enum.SubscriptionRequestType_SNAPSHOT), +func queryMarketDataRequest44(senderCompId, targetCompId string) fix44mdr.MarketDataRequest { + request := fix44mdr.New(field.NewMDReqID(strconv.Itoa(time.Now().Nanosecond())), + field.NewSubscriptionRequestType(enum.SubscriptionRequestType_SNAPSHOT_PLUS_UPDATES), field.NewMarketDepth(0), ) + request.SetMDUpdateType(enum.MDUpdateType_INCREMENTAL_REFRESH) entryTypes := fix44mdr.NewNoMDEntryTypesRepeatingGroup() + //noOfMDEntryTypes := entryTypes.Add() entryTypes.Add().SetMDEntryType(enum.MDEntryType_BID) + entryTypes.Add().SetMDEntryType(enum.MDEntryType_OFFER) request.SetNoMDEntryTypes(entryTypes) relatedSym := fix44mdr.NewNoRelatedSymRepeatingGroup() - relatedSym.Add().SetSymbol("LNUX") + // relatedSym.Add().SetSymbol("ETH-USD") + relatedSym.Add().SetSymbol("BTC-USD") request.SetNoRelatedSym(relatedSym) - queryHeader(request.Header) + setHeader(request.Header, senderCompId, targetCompId) return request } @@ -511,18 +537,19 @@ func queryMarketDataRequest50() fix50mdr.MarketDataRequest { return request } -func QueryEnterOrder() (err error) { +func QueryEnterOrder(senderCompId, targetCompId string) (err error) { defer func() { if e := recover(); e != nil { err = e.(error) } }() - var beginString string - beginString, err = queryVersion() - if err != nil { - return err - } + var beginString string = "FIX.4.4" + /* + beginString, err = queryVersion() + if err != nil { + return err + }*/ var order quickfix.Messagable switch beginString { @@ -539,8 +566,29 @@ func QueryEnterOrder() (err error) { order = queryNewOrderSingle43() case quickfix.BeginStringFIX44: - order = queryNewOrderSingle44() + symbol := "BTC-USD" + price := "60000" + var side, qty string + + start := time.Now() + midsize := 0.01 + for i := range 1 { + if i%2 == 0 { + side = "2" + qty = fmt.Sprintf("%f", midsize+float64(rand.Intn(10))/1000.0) + } else { + side = "2" + qty = fmt.Sprintf("%f", midsize-float64(rand.Intn(10))/1000.0) + } + //fmt.Printf("qty=%v,symbol=%s\n", qty,symbol) + order = queryNewOrderSingle44(senderCompId, targetCompId, side, symbol, qty, price) + quickfix.Send(order) + time.Sleep(1000 * time.Millisecond) + } + totoalTime := time.Since(start).Milliseconds() + fmt.Printf("sent 1000 orders in %v", totoalTime) + return case quickfix.BeginStringFIXT11: order = queryNewOrderSingle50() } @@ -589,7 +637,7 @@ func QueryCancelOrder() (err error) { return } -func QueryMarketDataRequest() error { +func QueryMarketDataRequest(senderCompId, targetCompId string) error { beginString, err := queryVersion() if err != nil { return err @@ -604,18 +652,19 @@ func QueryMarketDataRequest() error { req = queryMarketDataRequest43() case quickfix.BeginStringFIX44: - req = queryMarketDataRequest44() + req = queryMarketDataRequest44(senderCompId, targetCompId) case quickfix.BeginStringFIXT11: req = queryMarketDataRequest50() default: - return fmt.Errorf("No test for version %v", beginString) + return fmt.Errorf("no test for version %v", beginString) } - if queryConfirm("Send MarketDataRequest") { - return quickfix.Send(req) - } + //if queryConfirm("Send MarketDataRequest") { + fmt.Println("quickfix.Send(req)=>") + return quickfix.Send(req) + //} - return nil -} + //return nil +} \ No newline at end of file diff --git a/cmd/tradeclient/tradeclient.go b/cmd/tradeclient/tradeclient.go index 9f17d53..e4daa2b 100644 --- a/cmd/tradeclient/tradeclient.go +++ b/cmd/tradeclient/tradeclient.go @@ -17,15 +17,20 @@ package tradeclient import ( "bytes" + "crypto/ed25519" + "encoding/hex" "fmt" "io" "os" "path" + "strconv" "github.com/quickfixgo/examples/cmd/tradeclient/internal" "github.com/quickfixgo/examples/cmd/utils" "github.com/spf13/cobra" + "github.com/quickfixgo/field" + "github.com/quickfixgo/fix44/logon" "github.com/quickfixgo/quickfix" ) @@ -34,21 +39,88 @@ type TradeClient struct { } // OnCreate implemented as part of Application interface -func (e TradeClient) OnCreate(sessionID quickfix.SessionID) {} +func (e TradeClient) OnCreate(sessionID quickfix.SessionID) { + fmt.Printf("initiator session Id: %s\n", sessionID) +} // OnLogon implemented as part of Application interface func (e TradeClient) OnLogon(sessionID quickfix.SessionID) {} // OnLogout implemented as part of Application interface -func (e TradeClient) OnLogout(sessionID quickfix.SessionID) {} +func (e TradeClient) OnLogout(sessionID quickfix.SessionID) { + fmt.Printf("OnLogout: %s\n", sessionID) +} // FromAdmin implemented as part of Application interface func (e TradeClient) FromAdmin(msg *quickfix.Message, sessionID quickfix.SessionID) (reject quickfix.MessageRejectError) { + utils.PrintInfo(fmt.Sprintf("FromAdmin: %s\n", msg.String())) return nil } +const ( + FIX_SEP = "\u0001" + Publickey = "public key" + Privatekey = "private key" + //use the api key ID for now + APIKey = "api key" +) + // ToAdmin implemented as part of Application interface -func (e TradeClient) ToAdmin(msg *quickfix.Message, sessionID quickfix.SessionID) {} +func (e TradeClient) ToAdmin(msg *quickfix.Message, sessionID quickfix.SessionID) { + msgType, err := msg.MsgType() + if err != nil { + println("wrong message type") + } + + if msgType == "A" { + msg.Body.Set(field.NewPassword(APIKey)) + signature, err := e.sign(msg) + if err != nil { + println("error in sign the message") + } + msg.Body.Set(field.NewRawData(signature)) + } + + utils.PrintInfo(fmt.Sprintf("ToAdmin: %s", msg.String())) +} + +func (e TradeClient) sign(logonmsg *quickfix.Message) (string, error) { + msg := logon.FromMessage(logonmsg) + + sendingTime, err := msg.GetSendingTime() + if err != nil { + println("error in getting SendingTime from the logon") + return "", &quickfix.RejectLogon{Text: "invalid SendingTime"} + } + + seqNum, err := msg.GetMsgSeqNum() + if err != nil { + println("error in getting MsgSeqNum from the logon") + return "", &quickfix.RejectLogon{Text: "invalid MsgSeqNum"} + } + + senderCompID, err := msg.GetSenderCompID() + if err != nil { + println("error in getting SenderCompID from the logon") + return "", &quickfix.RejectLogon{Text: "invalid SenderCompID"} + } + + targetCompID, err := msg.GetTargetCompID() + if err != nil { + println("error in getting TargetCompID from the logon") + return "", &quickfix.RejectLogon{Text: "invalid TargetCompID"} + } + + msgToSign := sendingTime.Format("20060102-15:04:05.000") + FIX_SEP + + strconv.Itoa(seqNum) + FIX_SEP + + senderCompID + FIX_SEP + + targetCompID + + privateKeyBytes, _ := hex.DecodeString(Privatekey) + ed25519PrivateKey := ed25519.PrivateKey(privateKeyBytes) + signature := ed25519.Sign(ed25519PrivateKey, []byte(msgToSign)) + return hex.EncodeToString(signature), nil +} // ToApp implemented as part of Application interface func (e TradeClient) ToApp(msg *quickfix.Message, sessionID quickfix.SessionID) (err error) { @@ -135,6 +207,17 @@ func execute(cmd *cobra.Command, args []string) error { utils.PrintConfig("initiator", bytes.NewReader(stringData)) + /* + var senderCompId, targetCompID string + globalsettings := appSettings.GlobalSettings() + if globalsettings.HasSetting(config.SenderCompID){ + senderCompId,_ = globalsettings.Setting(config.SenderCompID) + } + if globalsettings.HasSetting(config.TargetCompID){ + targetCompID,_ = globalsettings.Setting(config.TargetCompID) + } + */ + Loop: for { action, err := internal.QueryAction() @@ -144,14 +227,13 @@ Loop: switch action { case "1": - err = internal.QueryEnterOrder() + err = internal.QueryEnterOrder("CUST2_Order", "an") case "2": err = internal.QueryCancelOrder() case "3": - err = internal.QueryMarketDataRequest() - + err = internal.QueryMarketDataRequest("CUST2_Marketdata", "an") case "4": //quit break Loop diff --git a/config/executor.cfg b/config/executor.cfg index b0f7f62..4daf2b3 100644 --- a/config/executor.cfg +++ b/config/executor.cfg @@ -5,21 +5,21 @@ TargetCompID=TW ResetOnLogon=Y FileLogPath=tmp -[SESSION] -BeginString=FIX.4.0 +#[SESSION] +#BeginString=FIX.4.0 -[SESSION] -BeginString=FIX.4.1 +#[SESSION] +#BeginString=FIX.4.1 -[SESSION] -BeginString=FIX.4.2 +#[SESSION] +#BeginString=FIX.4.2 -[SESSION] -BeginString=FIX.4.3 +#[SESSION] +#BeginString=FIX.4.3 [SESSION] BeginString=FIX.4.4 -[SESSION] -BeginString=FIXT.1.1 -DefaultApplVerID=7 +#[SESSION] +#BeginString=FIXT.1.1 +#DefaultApplVerID=7 \ No newline at end of file diff --git a/config/ordermatch.cfg b/config/ordermatch.cfg index b0f7f62..9459cb5 100644 --- a/config/ordermatch.cfg +++ b/config/ordermatch.cfg @@ -4,22 +4,27 @@ SenderCompID=ISLD TargetCompID=TW ResetOnLogon=Y FileLogPath=tmp +OrdersPerSecond=10 +ParallelSessions=5 +#SocketPrivateKeyFile=config/localhost.key +#SocketCertificateFile=config/localhost.crt +#SocketCAFile=config/ca.crt -[SESSION] -BeginString=FIX.4.0 +#[SESSION] +#BeginString=FIX.4.0 -[SESSION] -BeginString=FIX.4.1 +#[SESSION] +#BeginString=FIX.4.1 -[SESSION] -BeginString=FIX.4.2 +#[SESSION] +#BeginString=FIX.4.2 -[SESSION] -BeginString=FIX.4.3 +#[SESSION] +#BeginString=FIX.4.3 [SESSION] BeginString=FIX.4.4 -[SESSION] -BeginString=FIXT.1.1 -DefaultApplVerID=7 +#[SESSION] +#BeginString=FIXT.1.1 +#DefaultApplVerID=7 \ No newline at end of file diff --git a/config/tradeclient.cfg b/config/tradeclient.cfg index 52737fc..c6d4f64 100644 --- a/config/tradeclient.cfg +++ b/config/tradeclient.cfg @@ -1,27 +1,42 @@ [DEFAULT] -SocketConnectHost=127.0.0.1 -SocketConnectPort=5001 +SocketConnectHost=localhost HeartBtInt=30 -SenderCompID=TW -TargetCompID=ISLD ResetOnLogon=Y FileLogPath=tmp +SocketPrivateKeyFile=config/client0.key +SocketCertificateFile=config/client0.crt +SocketCAFile=config/ca.crt +OrdersPerSecond=10 +ParallelSessions=5 -[SESSION] -BeginString=FIX.4.0 +#[SESSION] +#BeginString=FIX.4.0 -[SESSION] -BeginString=FIX.4.1 +#[SESSION] +#BeginString=FIX.4.1 -[SESSION] -BeginString=FIX.4.2 +#[SESSION] +#BeginString=FIX.4.2 -[SESSION] -BeginString=FIX.4.3 +#[SESSION] +#BeginString=FIX.4.3 [SESSION] +SocketConnectPort=5002 BeginString=FIX.4.4 +#SenderCompID=CUST1_Marketdata +SenderCompID=CUST2_Marketdata +#SenderCompID=CLIENT1_MD +TargetCompID=ANCHORAGE [SESSION] -BeginString=FIXT.1.1 -DefaultApplVerID=7 +SocketConnectPort=5001 +BeginString=FIX.4.4 +#SenderCompID=CUST1_Order +SenderCompID=CUST2_Order +#SenderCompID=CLIENT1_Order +TargetCompID=ANCHORAGE + +#[SESSION] +#BeginString=FIXT.1.1 +#DefaultApplVerID=7 \ No newline at end of file diff --git a/go.mod b/go.mod index 1cfecdc..db728b8 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/quickfixgo/examples -go 1.21 +go 1.23.1 require ( github.com/fatih/color v1.16.0 @@ -31,4 +31,4 @@ require ( github.com/spf13/pflag v1.0.5 // indirect golang.org/x/net v0.18.0 // indirect golang.org/x/sys v0.14.0 // indirect -) +) \ No newline at end of file