Exemplo n.º 1
0
static int md_snapshot(struct fast_book *book, struct fast_message *msg)
{
	struct price_level *levels;
	struct fast_decimal price;
	struct fast_field *field;
	struct price_level level;
	char type;
	i64 size;
	u32 ind;

	field = fast_get_field(msg, "MDEntryType");
	if (!field || field_state_empty(field))
		goto fail;

	type = field->string_value[0];
	if (type == '0') {
		levels = book->ob.bids;
	} else if (type == '1') {
		levels = book->ob.asks;
	} else if (type == 'J') {
		book_add_flags(book, FAST_BOOK_EMPTY);
		goto exit;
	} else {
		goto fail;
	}

	field = fast_get_field(msg, "MDPriceLevel");
	if (!field || field_state_empty(field))
		goto fail;

	ind = field->uint_value - 1;

	field = fast_get_field(msg, "MDEntrySize");
	if (!field || field_state_empty(field))
		goto fail;

	size = field->int_value;

	field = fast_get_field(msg, "MDEntryPx");
	if (!field || field_state_empty(field))
		goto fail;

	price = field->decimal_value;
	if (price_align(&price, &book->tick))
		goto fail;

	level.price = price.mnt;
	level.size = size;

	if (set_price_level(levels, book->ob.depth, &level, ind))
		goto fail;

exit:
	return 0;

fail:
	return -1;
}
Exemplo n.º 2
0
static int apply_snapshot(struct fast_book_set *set, struct fast_book *dst, struct fast_message *msg)
{
	struct fast_sequence *seq;
	struct fast_field *field;
	struct fast_message *md;
	struct fast_book *book;
	int i;

	field = fast_get_field(msg, "SecurityID");
	if (!field || field_state_empty(field))
		goto fail;

	book = fast_book_find(set, field->uint_value);
	if (!book || book_has_flags(book, FAST_BOOK_ACTIVE))
		goto done;

	if (dst && dst->secid != book->secid)
		goto done;

	field = fast_get_field(msg, "MDEntries");
	if (!field || field_state_empty(field))
		goto fail;

	seq = field->ptr_value;
	if (field_state_empty(&seq->length))
		goto fail;

	field = fast_get_field(msg, "RptSeq");
	if (!field || field_state_empty(field))
		goto fail;

	book->rptseq = field->uint_value;

	book_clear_flags(book, FAST_BOOK_EMPTY);
	book_add_mask(set, book);

	for (i = 1; i <= seq->length.uint_value; i++) {
		md = seq->elements + i;

		if (md_snapshot(book, md))
			goto fail;
	}

	if (!fast_book_is_valid(book)) {
		if (!book_has_flags(book, FAST_BOOK_EMPTY))
			goto fail;
	} else {
		book_add_flags(book, FAST_BOOK_ACTIVE);
	}

done:
	return 0;

fail:
	return -1;
}
Exemplo n.º 3
0
int fast_books_subscribe(struct fast_book_set *set, struct fast_book *book)
{
	if (fast_books_join(set, book))
		goto fail;

	book_add_flags(book, FAST_BOOK_SUBSCRIBED);

	return 0;

fail:
	return -1;
}
Exemplo n.º 4
0
static int fast_books_join(struct fast_book_set *set, struct fast_book *book)
{
	struct fast_message *inc_msg = NULL;
	struct fast_message *snp_msg = NULL;
	bool snp_received = false;
	struct fast_field *field;
	struct fast_book *sbook;
	struct ob_level *level;
	struct ob_order order;
	u64 last_msg_seq_num;
	u64 msg_num_init = 0;
	u64 msg_num_cur = 0;
	GList *list;

	if (fast_feed_open(set->snp_feeds))
		goto fail;

	book_clear_flags(book, FAST_BOOK_ACTIVE);
	book_add_flags(book, FAST_BOOK_JOIN);

	while (!book_has_flags(book, FAST_BOOK_ACTIVE)) {
		if (next_increment(set, &inc_msg))
			goto fail;

		if (inc_msg) {
			if (apply_increment(set, NULL, inc_msg))
				goto fail;

			field = fast_get_field(inc_msg, "MsgSeqNum");

			if (!field || field_state_empty(field))
				goto fail;

			msg_num_cur = field->uint_value;

			if (!msg_num_init)
				msg_num_init = msg_num_cur;
		}

		if (!snp_received) {
			if (next_snapshot(set, &snp_msg))
				goto fail;
		}

		if (snp_msg) {
			field = fast_get_field(snp_msg, "SecurityID");
			if (field) {
				if (field_state_empty(field))
					goto fail;

				sbook = fast_book_by_id(set, field->uint_value);
				if (!sbook || book->secid != sbook->secid)
					continue;
			} else {
				field = fast_get_field(snp_msg, "Symbol");
				if (!field || field_state_empty(field))
					goto fail;

				sbook = fast_book_by_symbol(set, field->string_value);
				if (!sbook || strcmp(sbook->symbol, book->symbol))
					continue;
			}

			field = fast_get_field(snp_msg, "LastMsgSeqNumProcessed");
			if (!field || field_state_empty(field))
				goto fail;

			last_msg_seq_num = field->uint_value;

			if (!msg_num_init)
				continue;

			if (last_msg_seq_num < msg_num_init)
				continue;

			snp_received = true;

			if (last_msg_seq_num > msg_num_cur)
				continue;

			if (apply_snapshot(set, book, snp_msg))
				goto fail;

			if (book_has_flags(book, FAST_BOOK_EMPTY))
				snp_received = false;
		}
	}

	order.buy = false;
	list = g_list_first(book->ob.glasks);
	while (list) {
		level = g_list_nth_data(list, 0);
		list = g_list_next(list);

		if (!level->size) {
			order.price = level->price;

			if (ob_level_delete(&book->ob, &order))
				goto fail;
		}
	}

	order.buy = true;
	list = g_list_first(book->ob.glbids);
	while (list) {
		level = g_list_nth_data(list, 0);
		list = g_list_next(list);

		if (!level->size) {
			order.price = level->price;

			if (ob_level_delete(&book->ob, &order))
				goto fail;
		}
	}

	book_clear_flags(book, FAST_BOOK_JOIN);

	if (fast_feed_close(set->snp_feeds))
		goto fail;

	return 0;

fail:
	fast_feed_close(set->snp_feeds);

	return -1;
}
Exemplo n.º 5
0
static int md_increment(struct fast_book *book, struct fast_message *msg)
{
	struct fast_decimal price;
	struct fast_field *field;
	struct ob_order order;
	char type;
	i64 size;

	field = fast_get_field(msg, "MDEntryType");
	if (!field || field_state_empty(field))
		goto fail;

	type = field->string_value[0];
	if (type == '0') {
		order.buy = true;
	} else if (type == '1') {
		order.buy = false;
	} else if (type == 'J') {
		book_add_flags(book, FAST_BOOK_EMPTY);
		goto exit;
	} else {
		goto fail;
	}

	field = fast_get_field(msg, "MDEntrySize");
	if (!field || field_state_empty(field))
		goto fail;

	switch (field->type) {
	case FAST_TYPE_INT:
		size = field->int_value;
		break;
	case FAST_TYPE_DECIMAL:
		if (decimal_to_int(&field->decimal_value, &size))
			goto fail;
		break;
	case FAST_TYPE_UINT:
	case FAST_TYPE_STRING:
	case FAST_TYPE_VECTOR:
	case FAST_TYPE_SEQUENCE:
	default:
		goto fail;
	}

	field = fast_get_field(msg, "MDEntryPx");
	if (!field || field_state_empty(field))
		goto fail;

	price = field->decimal_value;
	if (price_align(&price, &book->tick))
		goto fail;

	order.seq_num = book->rptseq;
	order.price = price.mnt;
	order.size = size;

	field = fast_get_field(msg, "MDUpdateAction");
	if (!field || field_state_empty(field))
		goto fail;

	if (field->uint_value == 0) {
		if (ob_level_modify(&book->ob, &order))
			goto fail;
	} else if (field->uint_value == 1) {
		if (ob_level_modify(&book->ob, &order))
			goto fail;
	} else if (field->uint_value == 2) {
		if (book_has_flags(book, FAST_BOOK_ACTIVE)) {
			if (ob_level_delete(&book->ob, &order))
				goto fail;
		} else {
			order.size = 0;
			if (ob_level_modify(&book->ob, &order))
				goto fail;
		}
	} else {
		goto fail;
	}

exit:
	return 0;

fail:
	return -1;
}
Exemplo n.º 6
0
static int apply_snapshot(struct fast_book_set *set, struct fast_book *dst, struct fast_message *msg)
{
	struct fast_sequence *seq;
	struct fast_field *field;
	struct fast_message *md;
	struct fast_book *book;
	int i;

	field = fast_get_field(msg, "SecurityID");
	if (field) {
		if (field_state_empty(field))
			goto fail;

		book = fast_book_by_id(set, field->uint_value);
		if (!book || book_has_flags(book, FAST_BOOK_ACTIVE))
			goto done;

		if (!book_has_flags(book, FAST_BOOK_JOIN))
			goto done;

		if (dst && dst->secid != book->secid)
			goto done;
	} else {
		field = fast_get_field(msg, "Symbol");
		if (!field || field_state_empty(field))
			goto fail;

		book = fast_book_by_symbol(set, field->string_value);
		if (!book || book_has_flags(book, FAST_BOOK_ACTIVE))
			goto done;

		if (!book_has_flags(book, FAST_BOOK_JOIN))
			goto done;

		if (dst && strncmp(book->symbol, dst->symbol,
						strlen(dst->symbol)))
			goto done;
	}

	field = fast_get_field(msg, "MDEntries");
	if (!field) {
		field = fast_get_field(msg, "GroupMDEntries");
	}

	if (!field || field_state_empty(field))
		goto fail;

	seq = field->ptr_value;
	if (field_state_empty(&seq->length))
		goto fail;

	if (!seq->length.uint_value)
		goto done;

	md = seq->elements;

	field = fast_get_field(md, "TradingSessionID");
	if (field) {
		if (field_state_empty(field))
			goto fail;

		if (strncmp(book->session, field->string_value,
					strlen(book->session)))
			goto done;
	}

	field = fast_get_field(msg, "RptSeq");
	if (!field || field_state_empty(field))
		goto fail;

	book->snpseq = field->uint_value;

	book_clear_flags(book, FAST_BOOK_EMPTY);
	book_add_mask(set, book);

	for (i = 1; i <= seq->length.uint_value; i++) {
		md = seq->elements + i;

		if (md_snapshot(book, md))
			goto fail;
	}

	if (!book_has_flags(book, FAST_BOOK_EMPTY))
		book_add_flags(book, FAST_BOOK_ACTIVE);

done:
	return 0;

fail:
	return -1;
}