mdc

package module
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: Aug 18, 2026 License: MIT Imports: 11 Imported by: 0

README

MDC

CI Go Reference Release

MDC is a deterministic, self-contained market-data container for compact quote records. It combines a zero-allocation 32-bit 16/8/4/4 delta primitive with absolute block bases, explicit units, exact tick sizes, sessions, CRC32C, streaming, random access, and block-level recovery.

31                    16 15        8 7    4 3    0
+-----------------------+-----------+------+------+
|        deltaT         | deltaBid  |spread| flags|
|        16 bits        |  8 bits   |4 bits|4 bits|
+-----------------------+-----------+------+------+

What one MDC file carries

  • instrument identifier and economic price unit;
  • Unix timestamp unit (ns, us, ms, or s) and ordering contract;
  • exact rational tick size, normalized to lowest terms;
  • independent blocks with absolute timestamp and bid bases;
  • four-byte packed words for normal deltas;
  • sparse uint32 overrides for wide spread or flag values;
  • session and tick-size changes at block boundaries;
  • CRC32C for every file header, block header, block payload, and index section;
  • optional finite-file index for block and timestamp seeking.

There is no silent truncation in the canonical writer. A time gap, price jump, timestamp regression under source ordering, session change, or tick-size change starts a new independent block. Monotonic ordering violations are errors.

Install

go get github.com/marquesinteractive/go-mdc@v1.0.1
go install github.com/marquesinteractive/go-mdc/cmd/mdc@v1.0.1

MDC requires Go 1.22 or newer and has no runtime dependencies outside the standard library.

Go quick start

package main

import (
    "bytes"
    "fmt"

    mdc "github.com/marquesinteractive/go-mdc"
)

func main() {
    metadata := mdc.Metadata{
        Instrument: "WINFUT:B3",
        PriceUnit:  "index-point",
        TimeUnit:   mdc.TimeMillisecond,
        Ordering:   mdc.NonDecreasing,
        TickSize:   mdc.Rational{Num: 5, Den: 1},
        SpreadUnit: mdc.SpreadInTicks,
    }
    records := []mdc.Record{
        {Timestamp: 1_787_000_000_000, BidTicks: 34_910, Spread: 1, Session: 20260818},
        {Timestamp: 1_787_000_000_010, BidTicks: 34_911, Spread: 31, Flags: 0x120, Session: 20260818},
    }

    var encoded bytes.Buffer
    writer, err := mdc.NewWriter(&encoded, metadata)
    if err != nil {
        panic(err)
    }
    if _, err := writer.WriteBatch(records); err != nil {
        panic(err)
    }
    if err := writer.Close(); err != nil {
        panic(err)
    }

    reader, err := mdc.NewReader(bytes.NewReader(encoded.Bytes()))
    if err != nil {
        panic(err)
    }
    record, err := reader.ReadTick()
    if err != nil {
        panic(err)
    }
    fmt.Println(reader.Metadata().Instrument, record.BidTicks)
}

Writer.Close flushes the final block and writes the finite-file index. It does not close the underlying io.Writer.

Performance

Operation Reference result
Pack 2.804 ns/op
Unpack 1.685 ns/op
Batch pack 2.028 GiB/s

Reference measurements on an Intel Core i5-13400F with Go 1.26.2 and GOMAXPROCS=1. See BENCHMARKS.md for methodology, variance, scope, and reproduction commands.

CLI

The CLI accepts a strict five- or seven-column CSV schema and commits output through a synced temporary file. It refuses to overwrite an existing path.

mdc encode \
  --instrument WINFUT:B3 \
  --price-unit index-point \
  --time-unit ms \
  --ordering source \
  --tick-size 5/1 \
  ticks.csv ticks.mdc

mdc inspect ticks.mdc
mdc verify ticks.mdc
mdc decode ticks.mdc decoded.csv
mdc recover damaged.mdc recovered.mdc

Base CSV schema:

timestamp,bid_ticks,spread,flags,session

To change tick size within a file, append tick_size_num,tick_size_den. Both fields must be blank or both present. Input rationals are normalized before serialization.

Random access

Open validates the header, index, and trailer immediately. The selected block is validated when read.

file, err := os.Open("ticks.mdc")
if err != nil {
    panic(err)
}
defer file.Close()

reader, err := mdc.Open(file)
if err != nil {
    panic(err)
}
if err := reader.SeekTimestamp(targetUnixMillis); err != nil {
    panic(err)
}
record, err := reader.ReadTick()
if err != nil {
    panic(err)
}

Timestamp seeking requires NonDecreasing or StrictlyIncreasing ordering. SourceOrder files support block seeking but not temporal binary search.

Streaming

NewStreamWriter emits the same headers and independently verifiable blocks but omits the final index. A clean EOF is accepted only at a block boundary. A stream cannot prove that its producer intended to terminate.

writer, _ := mdc.NewStreamWriter(connection, metadata)
_ = writer.WriteTick(record)
_ = writer.Flush()
_ = writer.Close()

Recovery

Recover requires an intact metadata header. It scans byte boundaries for block magic and accepts a candidate only after dimensions, sequence-local semantics, header CRC32C, payload CRC32C, reserved fields, and overrides validate. Every accepted block is re-encoded into a new finite MDC file; unverified bytes are reported as damage ranges.

CRC32C detects accidental corruption. It does not authenticate hostile edits. Use a signature or authenticated envelope when provenance is adversarial.

Packed-word primitive

The low-level primitive remains available for applications that already own a separate schema and framing layer:

word, err := mdc.PackNormalChecked(25, -5, 1, 2)
delta := mdc.DecodeWord(word)

Its bit layout is deltaT:16 | deltaBid:8 | spread:4 | flags:4, serialized little-endian. Pack round-trips the complete uint32 word domain and masks the two four-bit fields by design. Use checked APIs for untrusted semantic input.

WritePackedWordsFile, ReadPackedWordsFile, PackedWordEncoder, and PackedWordDecoder operate on headerless words, not canonical .mdc containers. Their explicit names are intended to prevent format confusion.

Interoperability

Security and limits

Readers validate counts in wide integer types before narrowing or allocating. ReaderLimits bounds headers, block ticks, block bytes, overrides, and index entries. The defaults allow at most 1,048,576 ticks per block and 64 MiB per block. Writers cannot emit a block larger than the canonical default reader can accept.

The package contains no unsafe, assembly, CGo, memory mapping, or secondary compression layer. Such changes require measured evidence and a compatible failure model.

Scope

The current record schema stores timestamp, bid ticks, spread ticks, flags, session, and effective tick size. It does not encode volume, ask independently of spread, order-book depth, trade side, or venue-specific flag semantics. Applications must not claim full-feed losslessness unless every required source field is represented.

Versioning

The format has one public identity: MDC. formatMajor=1 and formatMinor=0 are wire-version fields, not separate product names.

See:

License

MIT. Copyright 2026 MarquesInteractive.

Documentation

Overview

Package mdc implements the canonical MDC container and its low-level packed word primitive for compact market data.

Index

Examples

Constants

View Source
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

View Source
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")
)
View Source
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")
)
View Source
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

func Pack(deltaT uint16, deltaBid int8, spread uint8, flag uint8) uint32

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

func PackChecked(deltaT uint16, deltaBid int8, spread uint8, flag uint8) (uint32, error)

PackChecked validates four-bit fields before encoding a tick.

func PackDeltas

func PackDeltas(dst []uint32, src []Delta) int

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

func PackNormalChecked(deltaT int64, deltaBid int64, spread uint8, flag uint8) (uint32, error)

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

func ReadPackedWordsFile(filename string) ([]uint32, error)

ReadPackedWordsFile reads a complete headerless packed-word stream.

func ReadPackedWordsFileLimit

func ReadPackedWordsFileLimit(filename string, maxTicks uint64) ([]uint32, error)

ReadPackedWordsFileLimit is ReadPackedWordsFile with an allocation guard. maxTicks=0 accepts only an empty stream.

func Unpack

func Unpack(packed uint32) (deltaT uint16, deltaBid int8, spread uint8, flag uint8)

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

func UnpackWords(dst []Delta, src []uint32) int

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

func WritePackedWords(w io.Writer, words []uint32) error

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

func WritePackedWordsBuffer(w io.Writer, words []uint32, buf []byte) error

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

func WritePackedWordsFile(filename string, words []uint32) error

WritePackedWordsFile writes a headerless packed-word stream. This is not a canonical MDC container; use Writer for self-contained .mdc files.

Types

type DamageRange

type DamageRange struct {
	Start uint64
	End   uint64
}

DamageRange identifies a byte interval that did not belong to a validated block during recovery. End is exclusive.

type Delta

type Delta struct {
	DeltaT   uint16
	DeltaBid int8
	Spread   uint8
	Flag     uint8
}

Delta represents the four fields embedded in one low-level packed word. Units and meanings come from the enclosing MDC container contract.

func DecodeWord

func DecodeWord(packed uint32) Delta

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

func (t Delta) Encode() uint32

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

func (t Delta) UsesEscapeMarker() bool

UsesEscapeMarker reports whether the tick contains a reserved escape marker. It does not validate any application-level overflow payload.

func (Delta) Validate

func (t Delta) Validate() error

Validate checks fields that can exceed their on-wire width.

func (Delta) ValidateNormal

func (t Delta) ValidateNormal() error

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 Ordering

type Ordering uint8

Ordering defines the timestamp contract of a container.

const (
	// SourceOrder preserves event order and starts a new block on timestamp regression.
	SourceOrder Ordering = iota
	// NonDecreasing rejects timestamp regressions.
	NonDecreasing
	// StrictlyIncreasing rejects equal or regressing timestamps.
	StrictlyIncreasing
)

type PackedWord

type PackedWord uint32

PackedWord is the type-safe in-memory form of one 16/8/4/4 word.

func (PackedWord) Decode

func (p PackedWord) Decode() Delta

Decode converts p to a Delta.

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 Rational

type Rational struct {
	Num int64
	Den uint64
}

Rational defines an exact positive price increment without floating point.

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 NewReader

func NewReader(r io.Reader) (*Reader, error)

NewReader creates a sequential reader with conservative allocation limits.

func NewReaderLimits

func NewReaderLimits(r io.Reader, limits ReaderLimits) (*Reader, error)

NewReaderLimits creates a sequential reader with explicit untrusted-input limits.

func (*Reader) Metadata

func (r *Reader) Metadata() Metadata

Metadata returns the file-level interpretation contract.

func (*Reader) ReadBatch

func (r *Reader) ReadBatch(dst []Record) (int, error)

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.

func (*Reader) ReadTick

func (r *Reader) ReadTick() (Record, error)

ReadTick returns the next fully reconstructed record.

func (*Reader) Verify

func (r *Reader) Verify() error

Verify consumes the remainder of the container and validates every block, checksum, sequence, index entry, and trailer.

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.

const (
	TimeNanosecond  TimeUnit = 1
	TimeMicrosecond TimeUnit = 2
	TimeMillisecond TimeUnit = 3
	TimeSecond      TimeUnit = 4
)

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

func NewStreamWriter(w io.Writer, metadata Metadata) (*Writer, error)

NewStreamWriter creates an open-ended MDC writer without a final index. Close still flushes the final block.

func NewWriter

func NewWriter(w io.Writer, metadata Metadata) (*Writer, error)

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

func NewWriterConfig(w io.Writer, metadata Metadata, config WriterConfig) (*Writer, error)

NewWriterConfig creates a writer with explicit block and index behavior.

func (*Writer) Close

func (w *Writer) Close() error

Close flushes the final block and writes the finite-file index when enabled. It does not close the underlying io.Writer.

func (*Writer) Flush

func (w *Writer) Flush() error

Flush emits the current independent block without closing the container.

func (*Writer) Metadata

func (w *Writer) Metadata() Metadata

Metadata returns the immutable file-level interpretation contract.

func (*Writer) WriteBatch

func (w *Writer) WriteBatch(records []Record) (int, error)

WriteBatch appends records in order and returns the number accepted before an error. A successful return always reports len(records).

func (*Writer) WriteTick

func (w *Writer) WriteTick(record Record) error

WriteTick appends one fully interpreted record.

type WriterConfig

type WriterConfig struct {
	MaxBlockTicks uint32
	WriteIndex    bool
}

WriterConfig controls block granularity and final index emission.

func DefaultWriterConfig

func DefaultWriterConfig() WriterConfig

DefaultWriterConfig returns the canonical finite-file configuration.

Directories

Path Synopsis
cmd
mdc command
examples
01_quickstart 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.

Jump to

Keyboard shortcuts

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