Documentation
¶
Overview ¶
Package mdc implements the canonical MDC container and its low-level packed word primitive for compact market data.
Index ¶
- Constants
- Variables
- func Pack(deltaT uint16, deltaBid int8, spread uint8, flag uint8) uint32
- func PackAbsoluteChecked(previousTimestamp, currentTimestamp int64, ...) (uint32, error)
- func PackChecked(deltaT uint16, deltaBid int8, spread uint8, flag uint8) (uint32, error)
- func PackDeltas(dst []uint32, src []Delta) int
- func PackNormalChecked(deltaT int64, deltaBid int64, spread uint8, flag uint8) (uint32, error)
- func ReadPackedWordsFile(filename string) ([]uint32, error)
- func ReadPackedWordsFileLimit(filename string, maxTicks uint64) ([]uint32, error)
- func Unpack(packed uint32) (deltaT uint16, deltaBid int8, spread uint8, flag uint8)
- func UnpackWords(dst []Delta, src []uint32) int
- func WritePackedWords(w io.Writer, words []uint32) error
- func WritePackedWordsBuffer(w io.Writer, words []uint32, buf []byte) error
- func WritePackedWordsFile(filename string, words []uint32) error
- type DamageRange
- type Delta
- type FileReader
- type Metadata
- type Ordering
- type PackedWord
- type PackedWordDecoder
- type PackedWordEncoder
- type Rational
- type Reader
- type ReaderLimits
- type Record
- type RecoveryReport
- type SpreadUnit
- type TimeUnit
- type Writer
- type WriterConfig
Examples ¶
Constants ¶
const ( // PackedWordSize is the serialized size of one low-level packed word, in bytes. PackedWordSize = 4 // EscapeTime is a reserved marker that an application-level protocol may use // when a time delta cannot be represented inline. MDC does not serialize the // corresponding absolute value; callers must define that side channel. EscapeTime uint16 = 0xFFFF // EscapePrice is a reserved marker that an application-level protocol may use // when a price delta cannot be represented inline. MDC does not serialize the // corresponding absolute value; callers must define that side channel. EscapePrice int8 = -128 // MaxDeltaT is the largest inline delta when EscapeTime is reserved. MaxDeltaT uint16 = 0xFFFE // MinDeltaBid is the smallest inline price delta when EscapePrice is reserved. MinDeltaBid int8 = -127 // MaxDeltaBid is the largest representable inline price delta. MaxDeltaBid int8 = 127 // MaxSpread is the maximum representable spread value (4 bits). MaxSpread uint8 = 0x0F // MaxFlag is the maximum representable flag value (4 bits). MaxFlag uint8 = 0x0F )
Variables ¶
var ( ErrInvalidMetadata = errors.New("mdc: invalid metadata") ErrInvalidRecord = errors.New("mdc: invalid record") ErrOrderingViolation = errors.New("mdc: ordering contract violated") ErrClosed = errors.New("mdc: writer is closed") ErrInvalidFormat = errors.New("mdc: invalid container format") ErrUnsupportedFormat = errors.New("mdc: unsupported container version or feature") ErrChecksumMismatch = errors.New("mdc: checksum mismatch") ErrLimitExceeded = errors.New("mdc: configured reader limit exceeded") ErrMissingIndex = errors.New("mdc: finite container index is missing") ErrIndexMismatch = errors.New("mdc: index does not match decoded blocks") ErrSequenceMismatch = errors.New("mdc: block sequence mismatch") )
var ( // ErrPackedWordAlignment indicates a byte length that is not a whole number of words. ErrPackedWordAlignment = errors.New("mdc: byte length is not aligned to a 4-byte packed-word boundary") // ErrPackedWordFileTooLarge indicates that the input cannot fit in a Go slice. ErrPackedWordFileTooLarge = errors.New("mdc: file contains too many packed words for this platform") // ErrPackedWordBufferTooSmall indicates that scratch space is shorter than one word. ErrPackedWordBufferTooSmall = errors.New("mdc: I/O buffer must hold at least one 4-byte packed word") // ErrPackedWordLimitExceeded indicates that ReadPackedWordsFileLimit rejected the // declared file size. ErrPackedWordLimitExceeded = errors.New("mdc: file exceeds configured packed-word limit") // ErrInvalidWrite indicates that an io.Writer violated the Writer contract. ErrInvalidWrite = errors.New("mdc: writer returned an invalid byte count") )
var ( // ErrDeltaTOutOfRange is returned when a normal semantic delta is outside // 0..MaxDeltaT. The raw word domain still round-trips EscapeTime. ErrDeltaTOutOfRange = errors.New("mdc: time delta outside normal semantic range") // ErrDeltaBidOutOfRange is returned when a normal semantic delta is outside // MinDeltaBid..MaxDeltaBid. The raw word domain still round-trips EscapePrice. ErrDeltaBidOutOfRange = errors.New("mdc: bid delta outside normal semantic range") // ErrSpreadOutOfRange is returned by checked APIs for spreads above 15. ErrSpreadOutOfRange = errors.New("mdc: spread exceeds 4-bit range") // ErrFlagOutOfRange is returned by checked APIs for flags above 15. ErrFlagOutOfRange = errors.New("mdc: flag exceeds 4-bit range") )
Functions ¶
func Pack ¶
Pack encodes the low four bits of spread and flag into one uint32.
Bit layout:
- deltaT: bits 0..15
- deltaBid: bits 16..23, in two's-complement form
- spread: bits 24..27
- flag: bits 28..31
Pack intentionally masks spread and flag for compatibility. Use PackChecked when silent truncation is not acceptable.
Example ¶
package main
import (
"fmt"
"github.com/marquesinteractive/go-mdc"
)
func main() {
// Pack 4 market parameters into a single 32-bit uint32
deltaT := uint16(25) // 25 milliseconds since last tick
deltaBid := int8(5) // +5 price steps (e.g. +25 points on WINFUT)
spread := uint8(1) // 1 step spread
flag := uint8(2) // Aggressor flag (e.g. 2 = Buyer Aggression)
packed := mdc.Pack(deltaT, deltaBid, spread, flag)
fmt.Printf("Packed: 0x%08X\n", packed)
}
Output: Packed: 0x21050019
func PackAbsoluteChecked ¶
func PackAbsoluteChecked( previousTimestamp, currentTimestamp int64, previousBidTicks, currentBidTicks int64, spread, flag uint8, ) (uint32, error)
PackAbsoluteChecked computes deltas from absolute int64 values and validates them before narrowing. It is the safe entry point when timestamps and bid prices have not already been converted to low-level delta types.
func PackChecked ¶
PackChecked validates four-bit fields before encoding a tick.
func PackDeltas ¶
PackDeltas packs as many deltas as fit in dst and returns the number written. It performs no allocations when dst is supplied by the caller.
func PackNormalChecked ¶
PackNormalChecked validates the low-level normal semantic domain before narrowing deltaT and deltaBid to their wire types. EscapeTime and EscapePrice remain round-trippable through Pack, PackChecked, and Unpack, but are rejected here because they are reserved by the normal semantic-domain convention.
func ReadPackedWordsFile ¶
ReadPackedWordsFile reads a complete headerless packed-word stream.
func ReadPackedWordsFileLimit ¶
ReadPackedWordsFileLimit is ReadPackedWordsFile with an allocation guard. maxTicks=0 accepts only an empty stream.
func Unpack ¶
Unpack decodes one uint32 into its constituent fields. The explicit uint8 conversion reconstructs the signed two's-complement byte without sign extension during the shift.
Example ¶
package main
import (
"fmt"
"github.com/marquesinteractive/go-mdc"
)
func main() {
packed := uint32(0x21050019)
deltaT, deltaBid, spread, flag := mdc.Unpack(packed)
fmt.Printf("deltaT: %dms, deltaBid: %+d, spread: %d, flag: %d\n",
deltaT, deltaBid, spread, flag)
}
Output: deltaT: 25ms, deltaBid: +5, spread: 1, flag: 2
func UnpackWords ¶
UnpackWords decodes as many words as fit in dst and returns the number written. It performs no allocations when dst is supplied by the caller.
func WritePackedWords ¶
WritePackedWords serializes low-level words to w in little-endian order. It uses one bounded work buffer and propagates short writes and writer errors.
func WritePackedWordsBuffer ¶
WritePackedWordsBuffer serializes words using caller-owned scratch space. A buffer of at least four bytes is required; extra bytes that do not form a complete word are ignored. Reusing the same buffer makes repeated bulk writes allocation-free.
func WritePackedWordsFile ¶
WritePackedWordsFile writes a headerless packed-word stream. This is not a canonical MDC container; use Writer for self-contained .mdc files.
Types ¶
type DamageRange ¶
DamageRange identifies a byte interval that did not belong to a validated block during recovery. End is exclusive.
type Delta ¶
Delta represents the four fields embedded in one low-level packed word. Units and meanings come from the enclosing MDC container contract.
func DecodeWord ¶
DecodeWord converts one packed uint32 to a Delta.
Example ¶
package main
import (
"fmt"
"github.com/marquesinteractive/go-mdc"
)
func main() {
packed := mdc.Pack(150, -10, 2, 4)
tick := mdc.DecodeWord(packed)
fmt.Printf("Decoded Tick: deltaT=%dms, deltaBid=%+d, spread=%d, flag=%d\n",
tick.DeltaT, tick.DeltaBid, tick.Spread, tick.Flag)
}
Output: Decoded Tick: deltaT=150ms, deltaBid=-10, spread=2, flag=4
func (Delta) Encode ¶
Encode converts a Delta to its uint32 representation. Like Pack, it masks the low-width fields; call Validate first when inputs are not trusted.
func (Delta) Pack ¶
func (t Delta) Pack() PackedWord
Pack returns the type-safe encoded representation of t.
func (Delta) UsesEscapeMarker ¶
UsesEscapeMarker reports whether the tick contains a reserved escape marker. It does not validate any application-level overflow payload.
func (Delta) ValidateNormal ¶
ValidateNormal validates t against the normal semantic domain, where EscapeTime and EscapePrice are reserved and require an outer protocol.
type FileReader ¶
type FileReader struct {
// contains filtered or unexported fields
}
FileReader provides validated random access to a finite indexed MDC file. The underlying ReadSeeker remains owned by the caller.
func Open ¶
func Open(reader io.ReadSeeker) (*FileReader, error)
Open validates the file header, trailer, and complete index without scanning every block payload. Each block is checksum-validated when read.
func OpenLimits ¶
func OpenLimits(reader io.ReadSeeker, limits ReaderLimits) (*FileReader, error)
OpenLimits is Open with explicit untrusted-input allocation limits.
func (*FileReader) BlockCount ¶
func (r *FileReader) BlockCount() int
BlockCount returns the number of independently checksummed blocks.
func (*FileReader) Metadata ¶
func (r *FileReader) Metadata() Metadata
Metadata returns the file-level interpretation contract.
func (*FileReader) ReadBatch ¶
func (r *FileReader) ReadBatch(dst []Record) (int, error)
ReadBatch fills dst from the current random-access position.
func (*FileReader) ReadTick ¶
func (r *FileReader) ReadTick() (Record, error)
ReadTick returns the next reconstructed record from the current position.
func (*FileReader) SeekBlock ¶
func (r *FileReader) SeekBlock(sequence uint32) error
SeekBlock positions the next read at the first tick of sequence.
func (*FileReader) SeekTimestamp ¶
func (r *FileReader) SeekTimestamp(target int64) error
SeekTimestamp positions the next read at the first tick whose timestamp is greater than or equal to target. SourceOrder files do not support temporal binary search because block bases may regress.
type Metadata ¶
type Metadata struct {
Instrument string
PriceUnit string
TimeUnit TimeUnit
Ordering Ordering
TickSize Rational
SpreadUnit SpreadUnit
}
Metadata is the self-contained interpretation contract for one MDC file. One file contains one instrument; session and tick-size changes are encoded at block boundaries.
type PackedWord ¶
type PackedWord uint32
PackedWord is the type-safe in-memory form of one 16/8/4/4 word.
func (PackedWord) Uint32 ¶
func (p PackedWord) Uint32() uint32
Uint32 exposes the primitive representation of p.
type PackedWordDecoder ¶
type PackedWordDecoder struct {
// contains filtered or unexported fields
}
PackedWordDecoder deserializes individual low-level words. It is not safe for concurrent use; synchronize access or use one per stream.
func NewPackedWordDecoder ¶
func NewPackedWordDecoder(r io.Reader) *PackedWordDecoder
NewPackedWordDecoder creates a low-level word decoder that reads from r.
func (*PackedWordDecoder) Decode ¶
func (d *PackedWordDecoder) Decode() (uint32, error)
Decode reads one packed word in little-endian order. It returns io.EOF when no bytes remain and io.ErrUnexpectedEOF for a truncated final word.
func (*PackedWordDecoder) DecodeDelta ¶
func (d *PackedWordDecoder) DecodeDelta() (Delta, error)
DecodeDelta reads and decodes one Delta.
type PackedWordEncoder ¶
type PackedWordEncoder struct {
// contains filtered or unexported fields
}
PackedWordEncoder serializes individual low-level words. It is not safe for concurrent use; synchronize access or use one encoder per stream.
func NewPackedWordEncoder ¶
func NewPackedWordEncoder(w io.Writer) *PackedWordEncoder
NewPackedWordEncoder creates a low-level word encoder that writes to w.
func (*PackedWordEncoder) Encode ¶
func (e *PackedWordEncoder) Encode(word uint32) error
Encode writes one packed word in little-endian order. It tolerates partial writes and returns io.ErrShortWrite if a writer makes no progress.
func (*PackedWordEncoder) EncodeDelta ¶
func (e *PackedWordEncoder) EncodeDelta(delta Delta) error
EncodeDelta validates and writes one decoded Delta.
type Reader ¶
type Reader struct {
// contains filtered or unexported fields
}
Reader verifies and decodes a canonical MDC container sequentially. It is not safe for concurrent use.
func NewReaderLimits ¶
func NewReaderLimits(r io.Reader, limits ReaderLimits) (*Reader, error)
NewReaderLimits creates a sequential reader with explicit untrusted-input limits.
func (*Reader) ReadBatch ¶
ReadBatch fills dst with reconstructed records. It returns io.EOF only when no records were produced; a final partial batch returns its count and nil.
type ReaderLimits ¶
type ReaderLimits struct {
MaxHeaderBytes uint64
MaxBlockTicks uint64
MaxBlockBytes uint64
MaxOverrides uint64
MaxIndexEntries uint64
}
ReaderLimits bounds all allocations derived from untrusted container fields.
func DefaultReaderLimits ¶
func DefaultReaderLimits() ReaderLimits
DefaultReaderLimits returns conservative limits suitable for ordinary files.
type Record ¶
type Record struct {
Timestamp int64
BidTicks int64
Spread uint32
Flags uint32
Session uint32
TickSize Rational
}
Record is one fully interpreted market tick. TickSize.Den==0 means continue using the current block tick size; a non-zero value changes it and starts a new independent block. Session changes also start a new block.
type RecoveryReport ¶
type RecoveryReport struct {
ScannedBytes uint64
RecoveredBlocks uint64
RecoveredTicks uint64
Damage []DamageRange
}
RecoveryReport describes the evidence preserved while rebuilding a damaged finite container.
func Recover ¶
func Recover(input io.ReadSeeker, output io.Writer, limits ReaderLimits) (RecoveryReport, error)
Recover scans a container with a valid file header and writes a new finite MDC container containing every independently checksum-valid block it can recover. It never copies an unverified block. Input and output must be different storage objects.
type SpreadUnit ¶
type SpreadUnit uint8
SpreadUnit defines how spread values are interpreted.
const (
SpreadInTicks SpreadUnit = 1
)
type TimeUnit ¶
type TimeUnit uint8
TimeUnit defines the unit used by absolute timestamps and deltaT.
type Writer ¶
type Writer struct {
// contains filtered or unexported fields
}
Writer emits the canonical self-contained MDC container. It is not safe for concurrent use. Blocks are independent and are flushed automatically when a delta cannot be represented, the session/tick size changes, or the configured block size is reached.
func NewStreamWriter ¶
NewStreamWriter creates an open-ended MDC writer without a final index. Close still flushes the final block.
func NewWriter ¶
NewWriter creates a finite MDC writer with an index and canonical defaults.
Example ¶
package main
import (
"bytes"
"fmt"
"github.com/marquesinteractive/go-mdc"
)
func main() {
metadata := mdc.Metadata{
Instrument: "EXAMPLE:X",
PriceUnit: "index-point",
TimeUnit: mdc.TimeMillisecond,
Ordering: mdc.NonDecreasing,
TickSize: mdc.Rational{Num: 5, Den: 1},
SpreadUnit: mdc.SpreadInTicks,
}
var output bytes.Buffer
writer, _ := mdc.NewWriter(&output, metadata)
_ = writer.WriteTick(mdc.Record{Timestamp: 1_000, BidTicks: 24_000, Spread: 1})
_ = writer.Close()
reader, _ := mdc.NewReader(bytes.NewReader(output.Bytes()))
record, _ := reader.ReadTick()
fmt.Printf("%s %d %d\n", reader.Metadata().Instrument, record.Timestamp, record.BidTicks)
}
Output: EXAMPLE:X 1000 24000
func NewWriterConfig ¶
NewWriterConfig creates a writer with explicit block and index behavior.
func (*Writer) Close ¶
Close flushes the final block and writes the finite-file index when enabled. It does not close the underlying io.Writer.
func (*Writer) WriteBatch ¶
WriteBatch appends records in order and returns the number accepted before an error. A successful return always reports len(records).
type WriterConfig ¶
WriterConfig controls block granularity and final index emission.
func DefaultWriterConfig ¶
func DefaultWriterConfig() WriterConfig
DefaultWriterConfig returns the canonical finite-file configuration.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
mdc
command
|
|
|
examples
|
|
|
01_quickstart
command
|
|
|
02_market_replay_backtest
command
|
|
|
03_tcp_streaming
command
|
|
|
tools
|
|
|
winfut-validation
command
Command winfut-validation validates a JSONL quote projection against MDC.
|
Command winfut-validation validates a JSONL quote projection against MDC. |