simplefixgo

package module
v1.14.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 12, 2023 License: AGPL-3.0 Imports: 13 Imported by: 0

README

Simple Fix

Generic badge Generic badge Generic badge Generic badge Generic badge

Table of contents

Table of contents

What is FIX?

FIX (a shorthand for Financial Information eXchange) is a widely adopted electronic communications protocol used for real-time exchange of information related to trading and markets. FIX connects the global ecosystem of venues, asset managers, banks/brokers, vendors and regulators by standardizing the communication among participants. FIX is a public-domain specification owned and maintained by FIX Protocol, Ltd (FPL).

Why SimpleFix Go?

SimpleFix Go is an open-source library that allows you to quickly integrate FIX messaging into your environment. The library is entirely written in Go, making it perfect for solutions powered by this programming language. SimpleFix Go supports any FIX API version. To learn about specifics of various FIX protocol versions, refer to the OnixS website.

You can provide your own extensions to SimpleFix Go and create a custom FIX dialect. This guide explains the basics of SimpleFix Go installation and provides examples illustrating how to configure and customize the library according to your requirements.

Main features
  • Adding custom fields to the FIX protocol
  • Adding custom messages to the FIX protocol
  • Adding custom types to the FIX protocol
  • Built-in session pipelines features
  • Built-in Acceptor (for the server side)
  • Built-in Initiator (for the client side)
  • Validation of incoming messages
  • Validation of outgoing messages
  • A demo server complete with mock data
  • Anything missing? Let us know!

Installing SimpleFix Go

To install SimpleFix Go, download the library by executing the following command:

$ go get -u github.com/b2broker/simplefix-go
  1. Install the Generator if you want to use your own XML schema providing a custom set of FIX messaging options:
$ cd $GOPATH/src/github.com/b2broker/simplefix-go && go install ./...

Using the Generator

The Generator is used to define the structure of FIX messages, as well as specify their tags and define message type constants and methods required to support any FIX API version.

Examples of code produced by the Generator can be found in the ./tests directory containing an automatically generated Go library based on a stripped-down FIX version 4.4. The library code is generated according to a scheme located in the ./source directory.

Generating a basic FIX library

The following code generates a FIX library based on an XML schema defining the library structure:

fixgen -o=./fix44 -s=./source/fix44.xml -t=./source/types.xml

After executing this command, the generated library code will be located in the ./fix44 directory.

Specifying Generator parameters

To create a custom FIX messaging library, prepare two XML files and specify the following parameters for the fixgen command:

-o — the output directory

-s — the path to the main XML schema

-t — the path to an XML file specifying value type mapping and informing the Generator about proper type casting (although the original FIX protocol features a lot of different value types, Go uses a smaller set of types that should be mapped to the FIX API)

Sample XML files are located in the ./source directory. You can use the existing files or modify them as required.

Getting started with SimpleFix Go

In this section, you will learn how to specify the session options and start a new FIX session as a client or as a server.

Specifying session options

The following sample code illustrates how to use a message builder to create various standard messages, as well as define fields and message tags required for FIX session pipelines. The fixgen command will generate the required structure in almost no time.

// In this code, fixgen is your generated FIX package:

var sessionOpts = session.Opts{
	MessageBuilders: session.MessageBuilders{
		HeaderBuilder:        fixgen.Header{}.New(),
		TrailerBuilder:       fixgen.Trailer{}.New(),
		LogonBuilder:         fixgen.Logon{}.New(),
		LogoutBuilder:        fixgen.Logout{}.New(),
		RejectBuilder:        fixgen.Reject{}.New(),
		HeartbeatBuilder:     fixgen.Heartbeat{}.New(),
		TestRequestBuilder:   fixgen.TestRequest{}.New(),
		ResendRequestBuilder: fixgen.ResendRequest{}.New(),
	},
	Tags: &messages.Tags{
		MsgType:         mustConvToInt(fixgen.FieldMsgType),
		MsgSeqNum:       mustConvToInt(fixgen.FieldMsgSeqNum),
		HeartBtInt:      mustConvToInt(fixgen.FieldHeartBtInt),
		EncryptedMethod: mustConvToInt(fixgen.FieldEncryptMethod),
	},
	AllowedEncryptedMethods: map[string]struct{}{
		fixgen.EnumEncryptMethodNoneother: {},
	},
	SessionErrorCodes: &messages.SessionErrorCodes{
		InvalidTagNumber:            mustConvToInt(fixgen.EnumSessionRejectReasonInvalidtagnumber),
		RequiredTagMissing:          mustConvToInt(fixgen.EnumSessionRejectReasonRequiredtagmissing),
		TagNotDefinedForMessageType: mustConvToInt(fixgen.EnumSessionRejectReasonTagNotDefinedForThisMessageType),
		UndefinedTag:                mustConvToInt(fixgen.EnumSessionRejectReasonUndefinedtag),
		TagSpecialWithoutValue:      mustConvToInt(fixgen.EnumSessionRejectReasonTagspecifiedwithoutavalue),
		IncorrectValue:              mustConvToInt(fixgen.EnumSessionRejectReasonValueisincorrectoutofrangeforthistag),
		IncorrectDataFormatValue:    mustConvToInt(fixgen.EnumSessionRejectReasonIncorrectdataformatforvalue),
		DecryptionProblem:           mustConvToInt(fixgen.EnumSessionRejectReasonDecryptionproblem),
		SignatureProblem:            mustConvToInt(fixgen.EnumSessionRejectReasonSignatureproblem),
		CompIDProblem:               mustConvToInt(fixgen.EnumSessionRejectReasonCompidproblem),
		Other:                       mustConvToInt(fixgen.EnumSessionRejectReasonOther),
	},
}
Starting as a client

The Initiator is a FIX API client that connects to an existing server.

The default Initiator implementation can be found in the ./initiator/main.go file.

Starting as a server

The Acceptor is a listener that accepts and handles client connection requests. According to the FIX protocol, the Acceptor can be both a provider and receiver of data, meaning that it can send requests to the clients as well as read data streams received from them.

The default Acceptor implementation can be found in the ./acceptor/main.go file.

Customizing messages

Adding custom message fields

The SimpleFix library features a default session package which provides all the necessary functionality for the standard FIX API pipelines, such as authentication, logging out, heartbeats, message rejects and handling of typical errors. For this reason, if you want to customize the default messages, such as Logon <A> or Heartbeat <0>, you should configure the Session structure in one of the following ways:

  • by integrating the existing structure into your custom procedure by way of composition, or simply copying the existing structure and modifying it in your client code

  • by modifying the message builder to account for the messages that you want to customize

Customizing the message builder

The standard Session structure accepts each MessageBuilder instance as an auto-generated Opts field. Each message builder is an interface, which means that you can create a custom builder, and the library will use it as the default one.

For example, if you want to add a new CounterPartyID field (tag number 22000) to you Logon message, you should modify your XML schema by adding a new field to the fields section and to your custom Logon message:


<fix>
    . . .
    <messages>
        <message name='Logon' msgcat='admin' msgtype='A'>
            . . .
            <field name='CounterPartyID' required='Y'/>
            ...
        </message>
    </messages>
    . . .
    <fields>
        <field number="22000" name="CounterPartyID" type="STRING"/>
    </fields>
    . . .
</fix>

While the rest of the code is generated by fixgen, you should specify this field manually using a custom builder:

// Your FIX package is generated by fixgen:

type CustomLogon struct {
    *fixgen.Logon
}

func (cl *CustomLogon) Build() messages.LogonBuilder {
    l := cl.Build()
    l.SetFieldCounterParty(os.Getenv("COUNTER_PARTY_ID"))
    return l
}

After this, you can use your CustomLogon structure (with a new field added to it) as a LogonBuilder in the default FIX API pipelines.

Documentation

Index

Constants

View Source
const AllMsgTypes = "ALL"

Variables

View Source
var (
	ErrNotEnoughMessages = errors.New("not enough messages in the storage")
	ErrInvalidBoundaries = errors.New("invalid boundaries")
	ErrInvalidSequence   = errors.New("unexpected sequence index")
)
View Source
var ErrConnClosed = fmt.Errorf("the reader is closed")

ErrConnClosed handles connection errors.

View Source
var ErrHandleNotFound = errors.New("handler not found")

ErrHandleNotFound is returned when a required handler is not found.

Functions

This section is empty.

Types

type Acceptor

type Acceptor struct {
	// contains filtered or unexported fields
}

Acceptor is a server-side service used for handling client connections.

func NewAcceptor

func NewAcceptor(listener net.Listener, factory HandlerFactory, writeTimeout time.Duration, handleNewClient func(handler AcceptorHandler)) *Acceptor

NewAcceptor is used to create a new Acceptor instance.

func (*Acceptor) Close

func (s *Acceptor) Close()

Close is called to cancel the Acceptor context and close a connection.

func (*Acceptor) ListenAndServe

func (s *Acceptor) ListenAndServe() error

ListenAndServe is used for listening and maintaining connections. It verifies and accepts connection requests from new clients.

type AcceptorHandler

type AcceptorHandler interface {
	ServeIncoming(msg []byte)
	Outgoing() <-chan []byte
	Run() error
	Stop()
	StopWithError(err error)
	Send(message SendingMessage) error
	SendBatch(messages []SendingMessage) error
	SendRaw(data []byte) error
	RemoveIncomingHandler(msgType string, id int64) (err error)
	RemoveOutgoingHandler(msgType string, id int64) (err error)
	HandleIncoming(msgType string, handle IncomingHandlerFunc) (id int64)
	HandleOutgoing(msgType string, handle OutgoingHandlerFunc) (id int64)
	OnDisconnect(handlerFunc utils.EventHandlerFunc)
	OnConnect(handlerFunc utils.EventHandlerFunc)
	OnStopped(handlerFunc utils.EventHandlerFunc)
	Context() context.Context
}

AcceptorHandler is a set of methods providing basic functionality to the Acceptor.

type AcceptorHandlerFactory

type AcceptorHandlerFactory struct {
	// contains filtered or unexported fields
}

AcceptorHandlerFactory is a handler factory for an Acceptor object.

func NewAcceptorHandlerFactory

func NewAcceptorHandlerFactory(msgTypeTag string, bufferSize int) *AcceptorHandlerFactory

NewAcceptorHandlerFactory returns a new AcceptorHandlerFactory instance.

func (*AcceptorHandlerFactory) MakeHandler

MakeHandler creates a new AcceptorHandler instance.

type Conn

type Conn struct {
	// contains filtered or unexported fields
}

Conn is a net.Conn wrapper that is used for handling split messages.

func NewConn

func NewConn(ctx context.Context, conn net.Conn, msgBuffSize int, writeDeadline time.Duration) *Conn

NewConn is called to create a new connection.

func (*Conn) Close

func (c *Conn) Close()

Close is called to cancel a connection context and close a connection.

func (*Conn) Reader

func (c *Conn) Reader() <-chan []byte

Reader returns a separate channel for handing incoming messages.

func (*Conn) Write

func (c *Conn) Write(msg []byte) error

Write is called to send messages to an outgoing socket.

type DefaultHandler

type DefaultHandler struct {
	// contains filtered or unexported fields
}

DefaultHandler is a standard handler for the Acceptor and Initiator objects.

func NewAcceptorHandler

func NewAcceptorHandler(ctx context.Context, msgTypeTag string, bufferSize int) *DefaultHandler

NewAcceptorHandler creates a handler for an Acceptor object.

func NewInitiatorHandler

func NewInitiatorHandler(ctx context.Context, msgTypeTag string, bufferSize int) *DefaultHandler

NewInitiatorHandler creates a handler for the Initiator object.

func (*DefaultHandler) Context

func (h *DefaultHandler) Context() context.Context

func (*DefaultHandler) HandleIncoming

func (h *DefaultHandler) HandleIncoming(msgType string, handle IncomingHandlerFunc) (id int64)

HandleIncoming subscribes a handler function to incoming messages with a specific msgType. To subscribe to all messages, specify the AllMsgTypes constant for the msgType field (such messages will have a higher priority than the ones assigned to specific handlers).

func (*DefaultHandler) HandleOutgoing

func (h *DefaultHandler) HandleOutgoing(msgType string, handle OutgoingHandlerFunc) (id int64)

HandleOutgoing subscribes a handler function to outgoing messages with a specific msgType (this may be required for modifying messages before sending). To subscribe to all messages, specify the AllMsgTypes constant for the msgType field (such messages will have a higher priority than the ones assigned to specific handlers).

func (*DefaultHandler) OnConnect

func (h *DefaultHandler) OnConnect(handlerFunc utils.EventHandlerFunc)

OnConnect handles connection events.

func (*DefaultHandler) OnDisconnect

func (h *DefaultHandler) OnDisconnect(handlerFunc utils.EventHandlerFunc)

OnDisconnect handles disconnection events.

func (*DefaultHandler) OnStopped

func (h *DefaultHandler) OnStopped(handlerFunc utils.EventHandlerFunc)

OnStopped handles session termination events.

func (*DefaultHandler) Outgoing

func (h *DefaultHandler) Outgoing() <-chan []byte

Outgoing is a service method that provides an outgoing channel to the server or client connection manager.

func (*DefaultHandler) RemoveIncomingHandler

func (h *DefaultHandler) RemoveIncomingHandler(msgType string, id int64) (err error)

RemoveIncomingHandler removes an existing handler for incoming messages.

func (*DefaultHandler) RemoveOutgoingHandler

func (h *DefaultHandler) RemoveOutgoingHandler(msgType string, id int64) (err error)

RemoveOutgoingHandler removes an existing handler for outgoing messages.

func (*DefaultHandler) Run

func (h *DefaultHandler) Run() (err error)

Run is a function that is used for listening and processing messages.

func (*DefaultHandler) Send

func (h *DefaultHandler) Send(message SendingMessage) error

Send is a function that sends a previously prepared message.

func (*DefaultHandler) SendBatch added in v1.11.0

func (h *DefaultHandler) SendBatch(messages []SendingMessage) error

SendBatch is a function that sends previously prepared messages.

func (*DefaultHandler) SendRaw

func (h *DefaultHandler) SendRaw(data []byte) error

SendRaw sends a message in the byte array format without involving any additional handlers.

func (*DefaultHandler) ServeIncoming

func (h *DefaultHandler) ServeIncoming(msg []byte)

ServeIncoming is an internal method for handling incoming messages.

func (*DefaultHandler) Stop

func (h *DefaultHandler) Stop()

Stop is a function that enables graceful termination of a session.

func (*DefaultHandler) StopWithError

func (h *DefaultHandler) StopWithError(err error)

StopWithError is a function that enables graceful termination of a session with throwing an error.

type HandlerFactory

type HandlerFactory interface {
	MakeHandler(ctx context.Context) AcceptorHandler
}

HandlerFactory creates handlers for the Acceptor.

type HandlerPool

type HandlerPool struct {
	// contains filtered or unexported fields
}

HandlerPool is used for managing the pool of message handlers.

func NewHandlerPool

func NewHandlerPool() *HandlerPool

NewHandlerPool creates a new HandlerPool instance.

func (*HandlerPool) Add

func (p *HandlerPool) Add(msgType string, handle OutgoingHandlerFunc) int64

Add is used to add a new message handler for the specified message type. The function returns the ID of a message for which a handler was added.

func (*HandlerPool) Remove

func (p *HandlerPool) Remove(msgType string, _ int64) error

Remove is used to remove a handler with a specified identifier.

type IncomingHandlerFunc

type IncomingHandlerFunc func(data []byte) bool

IncomingHandlerFunc is used for handling incoming messages.

type IncomingHandlerPool

type IncomingHandlerPool struct {
	*HandlerPool
}

IncomingHandlerPool is used to manage the pool of incoming messages stored in the form of byte arrays.

func NewIncomingHandlerPool

func NewIncomingHandlerPool() IncomingHandlerPool

NewIncomingHandlerPool creates a new HandlerPool instance.

func (*IncomingHandlerPool) Add

func (p *IncomingHandlerPool) Add(msgType string, handle IncomingHandlerFunc) int64

Add is used to add a new message handler for the specified message type. The function returns the ID of a message for which a handler was added.

func (IncomingHandlerPool) Range

func (p IncomingHandlerPool) Range(msgType string, f func(IncomingHandlerFunc) bool)

Range is used for traversal through handlers. The traversal stops if any handler returns false.

type Initiator

type Initiator struct {
	// contains filtered or unexported fields
}

Initiator provides the client-side service functionality.

func NewInitiator

func NewInitiator(conn net.Conn, handler InitiatorHandler, bufSize int, writeDeadline time.Duration) *Initiator

NewInitiator creates a new Initiator instance.

func (*Initiator) Close

func (c *Initiator) Close()

Close is used to cancel the specified Initiator context.

func (*Initiator) Send

func (c *Initiator) Send(message SendingMessage) error

Send is used to send a FIX message.

func (*Initiator) Serve

func (c *Initiator) Serve() error

Serve is used to initiate the procedure of delivering messages.

type InitiatorHandler

type InitiatorHandler interface {
	ServeIncoming(msg []byte)
	Outgoing() <-chan []byte
	Run() error
	StopWithError(err error)
	Send(message SendingMessage) error
	Context() context.Context
	Stop()
}

InitiatorHandler is an interface implementing basic methods required for handling the Initiator object.

type OutgoingHandlerFunc

type OutgoingHandlerFunc func(msg SendingMessage) bool

OutgoingHandlerFunc is used for handling outgoing messages.

type OutgoingHandlerPool

type OutgoingHandlerPool struct {
	*HandlerPool
}

OutgoingHandlerPool is used to manage the pool of outgoing messages stored as structures.

func NewOutgoingHandlerPool

func NewOutgoingHandlerPool() OutgoingHandlerPool

NewOutgoingHandlerPool creates a new OutgoingHandlerPool instance.

func (OutgoingHandlerPool) Range

func (p OutgoingHandlerPool) Range(msgType string, f func(OutgoingHandlerFunc) bool) (res bool)

Range is used for traversal through handlers. The traversal stops if any handler returns false.

type Sender

type Sender interface {
	Send(message SendingMessage) error
}

Sender is an interface implemented by any structure that can issue a SendingMessage.

type SendingMessage

type SendingMessage interface {
	HeaderBuilder() messages.HeaderBuilder
	MsgType() string
	ToBytes() ([]byte, error)
}

SendingMessage provides a basic method for sending messages.

Directories

Path Synopsis
cmd
examples
fix
storages

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL