Ejemplo 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;
}
Ejemplo 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;
}
Ejemplo n.º 3
0
int snprintmsg(char *buf, size_t size, struct fast_message *msg)
{
	struct fast_field *field;
	char delim = '|';
	int len = 0;
	int i;

	if (!msg)
		goto exit;

	if (len < size)
		len += snprintf(buf + len, size - len, "%c", delim);

	for (i = 0; i < msg->nr_fields && len < size; i++) {
		field = msg->fields + i;

		if (field_state_empty(field)) {
			len += snprintf(buf + len, size - len, "none%c", delim);
			continue;
		}

		switch (field->type) {
		case FAST_TYPE_INT:
			len += snprintf(buf + len, size - len, "%" PRId64 "%c", field->int_value, delim);
			break;
		case FAST_TYPE_UINT:
			len += snprintf(buf + len, size - len, "%" PRIu64 "%c", field->uint_value, delim);
			break;
		case FAST_TYPE_STRING:
			len += snprintf(buf + len, size - len, "%s%c", field->string_value, delim);
			break;
		case FAST_TYPE_DECIMAL:
			len += snprintf(buf + len, size - len, "%" PRId64 "%c", field->decimal_value.exp, delim);
			len += snprintf(buf + len, size - len, "%" PRId64 "%c", field->decimal_value.mnt, delim);
			break;
		case FAST_TYPE_SEQUENCE:
			len += snprintseq(buf + len, size - len, field);
			break;
		default:
			break;
		}
	}

exit:
	return len;
}
Ejemplo n.º 4
0
static int recv_snapshot(struct fast_book_set *set, struct fast_feed *feed, struct fast_message **next)
{
	struct fast_message *msg;
	struct fast_field *field;
	enum fix_msg_type type;

	*next = NULL;

	msg = fast_feed_recv(feed, 0);

	if (!msg) {
		goto done;
	} else if (fast_msg_has_flags(msg, FAST_MSG_FLAGS_RESET)) {
		fast_session_reset(feed->session);
		goto done;
	}

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

	type = fix_msg_type_parse(field->string_value, 0x00);

	switch (type) {
	case FIX_MSG_TYPE_SESSION_STATUS:
		break;
	case FIX_MSG_TYPE_SEQUENCE_RESET:
		break;
	case FIX_MSG_TYPE_HEARTBEAT:
		break;
	case FIX_MSG_TYPE_SNAPSHOT_REFRESH:
		*next = msg;

		break;
	default:
		goto fail;
	}

done:
	return 0;

fail:
	return -1;
}
Ejemplo n.º 5
0
int fmsgcmp(struct fast_message *expected, struct fast_message *actual)
{
	struct fast_field *expected_field;
	struct fast_field *actual_field;
	int ret = 1;
	int i;

	if (expected->nr_fields != actual->nr_fields)
		goto exit;

	for (i = 0; i < expected->nr_fields; i++) {
		actual_field = actual->fields + i;
		expected_field = expected->fields + i;

		if (actual_field->presence != expected_field->presence)
			goto exit;

		if (actual_field->type != expected_field->type)
			goto exit;

		if (actual_field->op != expected_field->op)
			goto exit;

		if (field_state_empty(actual_field)) {
			if (field_state_empty(expected_field))
				continue;
			else
				goto exit;
		}

		switch (expected_field->type) {
		case FAST_TYPE_INT:
			if (actual_field->int_value != expected_field->int_value)
				goto exit;
			break;
		case FAST_TYPE_UINT:
			if (actual_field->uint_value != expected_field->uint_value)
				goto exit;
			break;
		case FAST_TYPE_STRING:
			if (strcmp(actual_field->string_value, expected_field->string_value))
				goto exit;
			break;
		case FAST_TYPE_DECIMAL:
			if (actual_field->decimal_value.exp != expected_field->decimal_value.exp)
				goto exit;

			if (actual_field->decimal_value.mnt != expected_field->decimal_value.mnt)
				goto exit;

			break;
		case FAST_TYPE_SEQUENCE:
			break;
		default:
			break;
		}
	}

	ret = 0;

exit:
	return ret;
}
Ejemplo n.º 6
0
static int fast_books_join(struct fast_book_set *set, struct fast_book *book)
{
	struct fast_message *inc_buf = NULL;
	struct fast_message *tmp_buf;
	struct fast_field *field;
	struct fast_message *msg;
	unsigned long size = 32;
	unsigned long pos = 0;
	u64 last_msg_seq_num;
	u64 msg_seq_num = 0;
	unsigned long i;

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

	inc_buf = calloc(size, sizeof(struct fast_message));
	if (!inc_buf)
		goto fail;

	book_clear_flags(book, FAST_BOOK_ACTIVE);

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

		if (!msg)
			continue;

		if (apply_increment(set, NULL, msg))
			goto fail;

		if (pos >= size) {
			size *= 2;

			tmp_buf = realloc(inc_buf, size * sizeof(struct fast_message));
			if (!tmp_buf)
				goto fail;

			inc_buf = tmp_buf;
		}

		if (fast_message_copy(inc_buf + pos, msg)) {
			goto fail;
		} else
			pos++;

		if (!msg_seq_num) {
			field = fast_get_field(msg, "MsgSeqNum");

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

			msg_seq_num = field->uint_value;
		}

		if (next_snapshot(set, &msg))
			goto fail;

		if (!msg)
			continue;

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

		last_msg_seq_num = field->uint_value;

		if (last_msg_seq_num < msg_seq_num)
			continue;

		if (apply_snapshot(set, book, msg))
			goto fail;
	}

	if (!pos)
		goto fail;

	for (i = 0; i < pos; i++) {
		msg = inc_buf + i;

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

		msg_seq_num = field->uint_value;

		if (msg_seq_num <= last_msg_seq_num)
			continue;

		if (apply_increment(set, book, msg))
			goto fail;
	}

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

	fast_message_free(inc_buf, pos);

	return 0;

fail:
	fast_feed_close(set->snp_feeds);
	fast_message_free(inc_buf, pos);

	return -1;
}
Ejemplo n.º 7
0
static int recv_increment(struct fast_book_set *set, struct fast_feed *feed, struct fast_message **next)
{
	struct fast_message *msg;
	struct fast_field *field;
	enum fix_msg_type type;
	u64 msg_num;

	*next = NULL;

	if (feed->recv_num > set->inc_msg_num)
		goto done;

	msg = fast_feed_recv(feed, 0);

	if (!msg) {
		goto done;
	} else if (fast_msg_has_flags(msg, FAST_MSG_FLAGS_RESET)) {
		fast_session_reset(feed->session);
		goto done;
	}

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

	msg_num = field->uint_value;
	feed->recv_num = msg_num;

	if (!set->inc_msg_num) {
		set->inc_msg_num = msg_num;
	} else if (set->inc_msg_num + 1 == msg_num) {
		set->inc_msg_num++;

		if (set->inc_gap_mode)
			set->inc_gap_mode = false;
	} else if (set->inc_msg_num < msg_num) {
		set->inc_gap_mode = true;

		goto done;
	} else
		goto done;

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

	type = fix_msg_type_parse(field->string_value, 0x00);

	switch (type) {
	case FIX_MSG_TYPE_SESSION_STATUS:
		break;
	case FIX_MSG_TYPE_SEQUENCE_RESET:
		break;
	case FIX_MSG_TYPE_HEARTBEAT:
		break;
	case FIX_MSG_TYPE_INCREMENT_REFRESH:
		*next = msg;

		break;
	default:
		goto fail;
	}

done:
	return 0;

fail:
	return -1;
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
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;
}
Ejemplo n.º 10
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;
}