Skip to content
← All examples

Example 03

Parse fills

Reading text a person pasted: a few fills as CSV lines, parsed without

Category
Pure: runs anywhere
Permissions
None
Language
>=0.1.1, <0.2.0

Source

// Category: pure
// Permissions: none
// Reading text a person pasted: a few fills as CSV lines, parsed without
// guessing. A malformed line is reported, not skipped silently and not
// read as zero.

lang ">=0.1.1, <0.2.0";
import std.text;
import std.list;
import std.decimal;

struct Fill {
    symbol: String,
    side: String,
    px: Price,
    size: Quantity,
}

fn number(field: String, what: String) -> Result<Decimal, Error> {
    return match decimal.parse(field) {
        Some(d) => Ok(d),
        None => Err(error("E-CSV", "not a " + what + ": " + field)),
    };
}

fn parse_fill(line: String) -> Result<Fill, Error> {
    let fields = text.split(text.trim(line), ",");
    if fields.len() != 4 {
        return Err(error("E-CSV", "expected 4 fields, got " + to_string(fields.len()) + " in: " + line));
    }
    let px = number(fields[2], "price")?;
    let size = number(fields[3], "quantity")?;
    return Ok(Fill { symbol: text.to_upper(fields[0]), side: fields[1], px: price(px, USDT), size: qty(size) });
}

fn main() {
    let pasted = "btcusdt,buy,64000.5,0.010\nbtcusdt,sell,64100,0.004\nethusdt,buy,3200.25\nbtcusdt,sell,64150.5,abc";
    let mut fills: List<Fill> = [];
    let mut problems: List<String> = [];
    for line in text.split(pasted, "\n") {
        match parse_fill(line) {
            Ok(f) => {
                fills.push(f);
            }
            Err(e) => {
                problems.push(e.message);
            }
        }
    }
    let mut net = qty(0);
    for f in fills {
        if f.side == "buy" {
            net = net + f.size;
        } else {
            net = net - f.size;
        }
        print(f.symbol + " " + f.side + " " + to_string(f.size) + " @ " + to_string(f.px));
    }
    print("net BTC position " + to_string(net));
    print(to_string(problems.len()) + " line(s) refused:");
    for p in list.sort(problems) {
        print("  " + p);
    }
}
// expect-output: BTCUSDT buy 0.010 @ 64000.5 USDT
// expect-output: BTCUSDT sell 0.004 @ 64100 USDT
// expect-output: net BTC position 0.006
// expect-output: 2 line(s) refused:
// expect-output:   expected 4 fields, got 3 in: ethusdt,buy,3200.25
// expect-output:   not a quantity: abc