static int sse50etf_exec(void *data, void *data2) { RAII_VAR(struct msg *, msg, (struct msg *)data, msg_decr); Quote *quote = (Quote *)msg->data; struct wp *wp; NOT_USED(data2); if (isnan(cru) || isnan(ecc)) { xcb_log(XCB_LOG_WARNING, "No valid value for CRU or ECC"); goto end; } table_lock(contracts); if ((wp = table_get_value(contracts, quote->thyquote.m_cHYDM)) && (isnan(wp->price) || fabs(wp->price - quote->thyquote.m_dZXJ) > 0.000001)) { table_iter_t iter; table_node_t node; double sum = 0.0; time_t t = (time_t)quote->thyquote.m_nTime; struct tm lt; char datestr[64], res[512]; if (wp->type == 2) { table_unlock(contracts); goto end; } wp->price = quote->thyquote.m_dZXJ; iter = table_iter_new(contracts); while ((node = table_next(iter))) { wp = table_node_value(node); if (isnan(wp->price)) { xcb_log(XCB_LOG_WARNING, "No price info for '%s'", table_node_key(node)); table_iter_free(&iter); table_unlock(contracts); goto end; } sum += wp->weight * wp->price; } table_iter_free(&iter); strftime(datestr, sizeof datestr, "%F %T", localtime_r(&t, <)); snprintf(res, sizeof res, "SSE50ETF,%s.%03d|%f", datestr, quote->m_nMSec, (sum + ecc) / cru); out2rmp(res); } table_unlock(contracts); end: return 0; }
static int pd_exec(void *data, void *data2) { RAII_VAR(struct msg *, msg, (struct msg *)data, msg_decr); Quote *quote = (Quote *)msg->data; dlist_t dlist; NOT_USED(data2); if ((dlist = table_get_value(contracts, quote->thyquote.m_cHYDM))) { dlist_iter_t iter = dlist_iter_new(dlist, DLIST_START_HEAD); dlist_node_t node; while ((node = dlist_next(iter))) { struct cpl *cpl = (struct cpl *)dlist_node_value(node); pthread_spin_lock(&cpl->lock); if (!strcasecmp(cpl->contract1, quote->thyquote.m_cHYDM)) cpl->price1 = quote->thyquote.m_dZXJ; else cpl->price2 = quote->thyquote.m_dZXJ; if (cpl->price1 > 0.0 && cpl->price2 > 0.0) { float pd = fabs(cpl->price1 - cpl->price2); /* If the price diff changes, we output it. */ if (fabs(pd - cpl->prevpd) > 0.000001) { time_t t = (time_t)quote->thyquote.m_nTime; struct tm lt; char datestr[64], res[512]; strftime(datestr, sizeof datestr, "%F %T", localtime_r(&t, <)); snprintf(res, sizeof res, "PD,%s.%03d,%s,%s|%.2f,%.2f,%.2f", datestr, quote->m_nMSec, cpl->contract1, cpl->contract2, cpl->price1, cpl->price2, pd); out2rmp(res); cpl->prevpd = pd; } } pthread_spin_unlock(&cpl->lock); } } return 0; }
static int hello_exec(void *data, void *data2) { RAII_VAR(struct msg *, msg, (struct msg *)data, msg_decr); Quote *quote = (Quote *)msg->data; time_t t = (time_t)quote->thyquote.m_nTime; struct tm lt; char datestr[64], res[512]; NOT_USED(data2); strftime(datestr, sizeof datestr, "%F %T", localtime_r(&t, <)); snprintf(res, sizeof res, "HELLO,%s.%03d,%s|%.2f,%.2f,%.2f", datestr, quote->m_nMSec, quote->thyquote.m_cHYDM, quote->thyquote.m_dZXJ, quote->thyquote.m_dMRJG1, quote->thyquote.m_dMCJG1); out2rmp(res); return 0; }
static int ema_exec(void *data, void *data2) { RAII_VAR(struct msg *, msg, (struct msg *)data, msg_decr); Quote *quote = (Quote *)msg->data; float *price; map_iter_t *iter = map_iter_create(); deq_t *prices; int size; NOT_USED(data2); /* FIXME */ if (fabs(quote->thyquote.m_dZXJ) <= 0.000001) { xcb_log(XCB_LOG_WARNING, "Invalid quote: '%d,%d,%s,%.2f'", quote->thyquote.m_nTime, quote->m_nMSec, quote->thyquote.m_cHYDM, quote->thyquote.m_dZXJ); goto end; } if ((price = ALLOC(sizeof (float))) == NULL) { xcb_log(XCB_LOG_WARNING, "Error allocating memory for price"); goto end; } *price = quote->thyquote.m_dZXJ; pthread_mutex_lock(&conlock); map_find(iter, contracts, quote->thyquote.m_cHYDM); if (!map_iter_valid(iter, contracts)) { const char *contract; if ((contract = mem_strdup(quote->thyquote.m_cHYDM)) == NULL) { xcb_log(XCB_LOG_WARNING, "Error allocating memory for contract"); pthread_mutex_unlock(&conlock); FREE(price); goto end; } prices = deq_create(); map_insert(contracts, contract, prices); } else prices = map_iter_value(iter); deq_push_back(prices, price); if ((size = deq_size(prices)) == n) { int i; float ema = *((float *)deq_at(prices, 0)); time_t t = (time_t)quote->thyquote.m_nTime; struct tm lt; char datestr[64], res[256]; float *front; for (i = 1; i < size; ++i) ema = (2.0 / (n + 1)) * *((float *)deq_at(prices, i)) + (1 - (2.0 / (n + 1))) * ema; strftime(datestr, sizeof datestr, "%F %T", localtime_r(&t, <)); snprintf(res, sizeof res, "EMA,%s.%03d,%s|%.2f", datestr, quote->m_nMSec, quote->thyquote.m_cHYDM, ema); out2rmp(res); front = deq_front(prices); FREE(front); deq_pop_front(prices); } pthread_mutex_unlock(&conlock); map_iter_destroy(iter); end: return 0; }
static int impvbaw_exec(void *data, void *data2) { RAII_VAR(struct msg *, msg, (struct msg *)data, msg_decr); Quote *quote = (Quote *)msg->data; struct msgs *out = (struct msgs *)data2; dstr contract; float last; char *p; table_node_t node; contract = dstr_new(quote->thyquote.m_cHYDM); if (!strcmp(contract, "") || (fabs(quote->thyquote.m_dZXJ) <= 0.000001 && fabs(quote->thyquote.m_dMRJG1) <= 0.000001 && fabs(quote->thyquote.m_dMCJG1) <= 0.000001)) { xcb_log(XCB_LOG_WARNING, "Invalid quote: '%d,%d,%s,%.2f,%.2f,%.2f'", quote->thyquote.m_nTime, quote->m_nMSec, contract, quote->thyquote.m_dZXJ, quote->thyquote.m_dMRJG1, quote->thyquote.m_dMCJG1); goto end; } /* FIXME */ if (!strncasecmp(contract, "IO", 2) || !strncasecmp(contract, "HO", 2) || !strncasecmp(contract, "00", 2) || !strncasecmp(contract, "60", 2)) goto end; last = quote->thyquote.m_dZXJ; if ((p = strrchr(contract, 'C')) == NULL) p = strrchr(contract, 'P'); /* FIXME: option quote */ if (p && p != contract && p != contract + dstr_length(contract) - 1 && ((*(p - 1) == '-' && *(p + 1) == '-') || (isdigit(*(p - 1)) && isdigit(*(p + 1))))) { dstr spotname, type, strike; float spot; struct prices *prices; double expiry, vol, vol2, vol3; struct tm lt; char *res; spotname = *(p - 1) == '-' ? dstr_new_len(contract, p - contract - 1) : dstr_new_len(contract, p - contract); type = dstr_new_len(p, 1); strike = *(p + 1) == '-' ? dstr_new_len(p + 2, contract + dstr_length(contract) - p - 2) : dstr_new_len(p + 1, contract + dstr_length(contract) - p - 1); table_rwlock_rdlock(spots); if ((node = table_find(spots, spotname)) == NULL) { table_rwlock_unlock(spots); dstr_free(strike); dstr_free(type); dstr_free(spotname); goto end; } spot = table_node_float(node); table_rwlock_unlock(spots); if (fabs(spot) <= 0.000001) { xcb_log(XCB_LOG_WARNING, "The price of spot '%s' be zero", spotname); dstr_free(strike); dstr_free(type); dstr_free(spotname); goto end; } table_lock(optns); if ((node = table_find(optns, contract)) == NULL) { if (NEW(prices)) { prices->prelast = last; prices->prebid1 = quote->thyquote.m_dMRJG1; prices->preask1 = quote->thyquote.m_dMCJG1; prices->prespot = spot; table_insert(optns, dstr_new(contract), prices); } else xcb_log(XCB_LOG_WARNING, "Error allocating memory for prices"); } else { prices = (struct prices *)table_node_value(node); if (fabs(prices->prelast - last) <= 0.000001 && fabs(prices->prebid1 - quote->thyquote.m_dMRJG1) <= 0.000001 && fabs(prices->preask1 - quote->thyquote.m_dMCJG1) <= 0.000001 && fabs(prices->prespot - spot) <= 0.000001) { table_unlock(optns); dstr_free(strike); dstr_free(type); dstr_free(spotname); goto end; } else { prices->prelast = last; prices->prebid1 = quote->thyquote.m_dMRJG1; prices->preask1 = quote->thyquote.m_dMCJG1; prices->prespot = spot; } } table_unlock(optns); if ((node = table_find(expiries, contract))) expiry = table_node_double(node); else { char *month; struct timeval tv; int diff; xcb_log(XCB_LOG_WARNING, "No exact expiry date for '%s'", contract); month = spotname + dstr_length(spotname) - 2; gettimeofday(&tv, NULL); if ((diff = atoi(month) - localtime_r(&tv.tv_sec, <)->tm_mon - 1) < 0) diff += 12; if (diff == 0) diff = 1; expiry = diff / 12.0; } /* FIXME: last price */ if (fabs(last) <= 0.000001) vol = NAN; else vol = impv_baw(spot, atof(strike), r, r, expiry, last, !strcasecmp(type, "C") ? AMER_CALL : AMER_PUT); /* FIXME: bid price 1 */ if (fabs(quote->thyquote.m_dMRJG1) <= 0.000001) vol2 = NAN; else if (fabs(quote->thyquote.m_dMRJG1 - last) <= 0.000001) vol2 = vol; else vol2 = impv_baw(spot, atof(strike), r, r, expiry, quote->thyquote.m_dMRJG1, !strcasecmp(type, "C") ? AMER_CALL : AMER_PUT); /* FIXME: ask price 1 */ if (fabs(quote->thyquote.m_dMCJG1) <= 0.000001) vol3 = NAN; else if (fabs(quote->thyquote.m_dMCJG1 - last) <= 0.000001) vol3 = vol; else vol3 = impv_baw(spot, atof(strike), r, r, expiry, quote->thyquote.m_dMCJG1, !strcasecmp(type, "C") ? AMER_CALL : AMER_PUT); if ((res = ALLOC(512))) { time_t t = (time_t)quote->thyquote.m_nTime; char datestr[64]; strftime(datestr, sizeof datestr, "%F %T", localtime_r(&t, <)); snprintf(res, 512, "IMPVBAW,%s.%03d,%s|%.2f,%f,%.2f,%f,%.2f,%f,%.2f", datestr, quote->m_nMSec, contract, last, vol, quote->thyquote.m_dMRJG1, vol2, quote->thyquote.m_dMCJG1, vol3, spot); out2rmp(res); snprintf(res, 512, "IMPVBAW,%d,%d,%s,%.2f,%f,%.2f,%f,%.2f,%f,%.2f,%s,%s,%s,%f,%f,%d,0,0", quote->thyquote.m_nTime, quote->m_nMSec, contract, last, vol, quote->thyquote.m_dMRJG1, vol2, quote->thyquote.m_dMCJG1, vol3, spot, spotname, type, strike, r, expiry, quote->thyquote.m_nCJSL); if (out2msgs(res, out) == -1) FREE(res); } else xcb_log(XCB_LOG_WARNING, "Error allocating memory for result"); dstr_free(strike); dstr_free(type); dstr_free(spotname); /* future quote */ } else { table_rwlock_wrlock(spots); if ((node = table_find(spots, contract)) == NULL) { if ((node = table_insert_raw(spots, contract))) table_set_float(node, last); } else { table_set_float(node, last); dstr_free(contract); } table_rwlock_unlock(spots); return 0; } end: dstr_free(contract); return 0; }
static int mm_impvbaw_exec(void *data, void *data2) { RAII_VAR(struct msg *, msg, (struct msg *)data, msg_decr); dstr *fields = NULL; int nfield = 0; time_t t; dstr spotname; double vol; NOT_USED(data2); fields = dstr_split_len(msg->data, strlen(msg->data), ",", 1, &nfield); /* FIXME */ if (nfield != 19) { xcb_log(XCB_LOG_WARNING, "Message '%s' garbled", msg->data); goto end; } t = (time_t)atoi(fields[1]); spotname = dstr_new(fields[11]); vol = atof(fields[5]); if (!isnan(vol)) { struct mm *mm; int flag = 0; table_lock(contracts); if ((mm = table_get_value(contracts, spotname)) == NULL) { if (NEW(mm)) { mm->min = mm->max = vol; flag = 1; table_insert(contracts, spotname, mm); } else xcb_log(XCB_LOG_WARNING, "Error allocating memory for mm"); } else { if (mm->min > vol) { mm->min = vol; flag = 1; } else if (mm->max < vol) { mm->max = vol; flag = 1; } dstr_free(spotname); } if (mm && flag) { struct tm lt; char datestr[64], res[512]; localtime_r(&t, <); lt.tm_hour = lt.tm_min = lt.tm_sec = 0; strftime(datestr, sizeof datestr, "%F %T", <); snprintf(res, sizeof res, "MM_IMPVBAW,%s.000,%s|%f,%f", datestr, fields[11], mm->min, mm->max); out2rmp(res); } table_unlock(contracts); } end: dstr_free_tokens(fields, nfield); return 0; }
static int vxo_exec(void *data, void *data2) { RAII_VAR(struct msg *, msg, (struct msg *)data, msg_decr); struct msgs *out = (struct msgs *)data2; dstr *fields = NULL; int nfield = 0; double vol, vol2, vol3, spot, strike, r, expiry; int sec, msec; dstr spotname; char *type; struct pd *pd; struct scp *scp; fields = dstr_split_len(msg->data, strlen(msg->data), ",", 1, &nfield); /* FIXME */ if (nfield != 19) { xcb_log(XCB_LOG_WARNING, "Message '%s' garbled", msg->data); goto end; } vol = !strcasecmp(fields[5], "nan") ? NAN : atof(fields[5]); vol2 = !strcasecmp(fields[7], "nan") ? NAN : atof(fields[7]); vol3 = !strcasecmp(fields[9], "nan") ? NAN : atof(fields[9]); if (isnan(vol) && isnan(vol2) && isnan(vol3)) goto end; sec = atoi(fields[1]); msec = atoi(fields[2]); spot = atof(fields[10]); spotname = dstr_new(fields[11]); type = fields[12]; strike = atof(fields[13]); r = atof(fields[14]); expiry = atof(fields[15]); table_lock(spots); if ((pd = table_get_value(spots, spotname)) == NULL) { /* can't happen */ if (NEW(scp) == NULL) { xcb_log(XCB_LOG_WARNING, "Error allocating memory for scp"); table_unlock(spots); goto end; } scp->strike = strike; if (!strcasecmp(type, "C")) { scp->cvol = vol; scp->pvol = NAN; scp->cvol2 = vol2; scp->pvol2 = NAN; scp->cvol3 = vol3; scp->pvol3 = NAN; } else { scp->cvol = NAN; scp->pvol = vol; scp->cvol2 = NAN; scp->pvol2 = vol2; scp->cvol3 = NAN; scp->pvol3 = vol3; } if (NEW(pd) == NULL) { xcb_log(XCB_LOG_WARNING, "Error allocating memory for pd"); FREE(scp); table_unlock(spots); goto end; } pd->prevxo = pd->prevxo2 = pd->prevxo3 = NAN; pd->sep = strchr(fields[3], '-') ? "-" : ""; pd->dlist = dlist_new(NULL, scpfree); dlist_insert_tail(pd->dlist, scp); table_insert(spots, spotname, pd); } else { dlist_iter_t iter = dlist_iter_new(pd->dlist, DLIST_START_HEAD); dlist_node_t node; while ((node = dlist_next(iter))) { scp = (struct scp *)dlist_node_value(node); if (scp->strike > strike || fabs(scp->strike - strike) <= 0.000001) break; } if (node && fabs(scp->strike - strike) <= 0.000001) { if (!strcasecmp(type, "C")) { scp->cvol = vol; scp->cvol2 = vol2; scp->cvol3 = vol3; } else { scp->pvol = vol; scp->pvol2 = vol2; scp->pvol3 = vol3; } } else { /* can't happen */ if (NEW(scp) == NULL) { xcb_log(XCB_LOG_WARNING, "Error allocating memory for scp"); table_unlock(spots); goto end; } scp->strike = strike; if (!strcasecmp(type, "C")) { scp->cvol = vol; scp->pvol = NAN; scp->cvol2 = vol2; scp->pvol2 = NAN; scp->cvol3 = vol3; scp->pvol3 = NAN; } else { scp->cvol = NAN; scp->pvol = vol; scp->cvol2 = NAN; scp->pvol2 = vol2; scp->cvol3 = NAN; scp->pvol3 = vol3; } if (node == NULL) dlist_insert_tail(pd->dlist, scp); else dlist_insert(pd->dlist, node, scp, 0); } dlist_iter_rewind_head(iter, pd->dlist); while ((node = dlist_next(iter))) { scp = (struct scp *)dlist_node_value(node); if (scp->strike > spot || fabs(scp->strike - spot) <= 0.000001) break; } dlist_iter_free(&iter); if (node && dlist_node_prev(node)) { struct scp *scp1 = (struct scp *)dlist_node_value(node); struct scp *scp2 = (struct scp *)dlist_node_value(dlist_node_prev(node)); double vxo = NAN, vxo2 = NAN, vxo3 = NAN; int flag1, flag2, flag3; if (!isnan(scp1->cvol) && !isnan(scp1->pvol) && !isnan(scp2->cvol) && !isnan(scp2->pvol)) vxo = ((scp1->cvol + scp1->pvol) / 2) * (spot - scp2->strike) / (scp1->strike - scp2->strike) + ((scp2->cvol + scp2->pvol) / 2) * (scp1->strike - spot) / (scp1->strike - scp2->strike); if (!isnan(scp1->cvol2) && !isnan(scp1->pvol2) && !isnan(scp2->cvol2) && !isnan(scp2->pvol2)) vxo2 = ((scp1->cvol2 + scp1->pvol2) / 2) * (spot - scp2->strike) / (scp1->strike - scp2->strike) + ((scp2->cvol2 + scp2->pvol2) / 2) * (scp1->strike - spot) / (scp1->strike - scp2->strike); if (!isnan(scp1->cvol3) && !isnan(scp1->pvol3) && !isnan(scp2->cvol3) && !isnan(scp2->pvol3)) vxo3 = ((scp1->cvol3 + scp1->pvol3) / 2) * (spot - scp2->strike) / (scp1->strike - scp2->strike) + ((scp2->cvol3 + scp2->pvol3) / 2) * (scp1->strike - spot) / (scp1->strike - scp2->strike); if ((flag1 = (isnan(pd->prevxo) && !isnan(vxo)) || (!isnan(pd->prevxo) && isnan(vxo)) || (!isnan(pd->prevxo) && !isnan(vxo) && fabs(pd->prevxo - vxo) > 0.000001) ? 1 : 0)) pd->prevxo = vxo; if ((flag2 = (isnan(pd->prevxo2) && !isnan(vxo2)) || (!isnan(pd->prevxo2) && isnan(vxo2)) || (!isnan(pd->prevxo2) && !isnan(vxo2) && fabs(pd->prevxo2 - vxo2) > 0.000001) ? 1 : 0)) pd->prevxo2 = vxo2; if ((flag3 = (isnan(pd->prevxo3) && !isnan(vxo3)) || (!isnan(pd->prevxo3) && isnan(vxo3)) || (!isnan(pd->prevxo3) && !isnan(vxo3) && fabs(pd->prevxo3 - vxo3) > 0.000001) ? 1 : 0)) pd->prevxo3 = vxo3; if (flag1 || flag2 || flag3) { char *res; if ((res = ALLOC(4096))) { time_t t = (time_t)sec; struct tm lt; char datestr[64]; int off; strftime(datestr, sizeof datestr, "%F %T", localtime_r(&t, <)); snprintf(res, 4096, "VXO,%s.%03d,%s|%f,%f,%f", datestr, msec, spotname, vxo, vxo2, vxo3); out2rmp(res); off = snprintf(res, 4096, "VXO,%d,%d,%s,", sec, msec, spotname); iter = dlist_iter_new(pd->dlist, DLIST_START_HEAD); while ((node = dlist_next(iter))) { scp = (struct scp *)dlist_node_value(node); off += snprintf(res + off, 4096 - off, "%.f,%f,%f,%f,", scp->strike, vxo, vxo2, vxo3); } dlist_iter_free(&iter); snprintf(res + off, 4096 - off, "%.2f,%f,%f,%s", spot, r, expiry, pd->sep); if (out2msgs(res, out) == -1) FREE(res); } } } dstr_free(spotname); } table_unlock(spots); end: dstr_free_tokens(fields, nfield); return 0; }
static int greeks2_exec(void *data, void *data2) { RAII_VAR(struct msg *, msg, (struct msg *)data, msg_decr); dstr *fields = NULL; int nfield = 0; time_t t; char *contract, *type; double spot, strike, r, vol, vol2, vol3, expiry; int steps; NOT_USED(data2); fields = dstr_split_len(msg->data, strlen(msg->data), ",", 1, &nfield); /* FIXME */ if (nfield != 19) { xcb_log(XCB_LOG_WARNING, "Message '%s' garbled", msg->data); goto end; } t = (time_t)atoi(fields[1]); contract = fields[3]; type = fields[12]; spot = atof(fields[10]); strike = atof(fields[13]); r = atof(fields[14]); vol = atof(fields[5]); vol2 = atof(fields[7]); vol3 = atof(fields[9]); expiry = atof(fields[15]); steps = atoi(fields[18]); if (!isnan(vol) || !isnan(vol2) || !isnan(vol3)) { double delta, gamma, theta, vega, rho; double delta2, gamma2, theta2, vega2, rho2; double delta3, gamma3, theta3, vega3, rho3; struct tm lt; char datestr[64], res[512]; if (isnan(vol)) delta = gamma = theta = vega = rho = NAN; else { if (!strcasecmp(type, "C")) bi_amer_call_greeks(spot, strike, r, r, vol, expiry, steps, &delta, &gamma, &theta, &vega, &rho); else bi_amer_put_greeks (spot, strike, r, r, vol, expiry, steps, &delta, &gamma, &theta, &vega, &rho); } if (isnan(vol2)) delta2 = gamma2 = theta2 = vega2 = rho2 = NAN; else if (fabs(vol2 - vol) <= 0.000001) { delta2 = delta; gamma2 = gamma; theta2 = theta; vega2 = vega; rho2 = rho; } else { if (!strcasecmp(type, "C")) bi_amer_call_greeks(spot, strike, r, r, vol2, expiry, steps, &delta2, &gamma2, &theta2, &vega2, &rho2); else bi_amer_put_greeks (spot, strike, r, r, vol2, expiry, steps, &delta2, &gamma2, &theta2, &vega2, &rho2); } if (isnan(vol3)) delta3 = gamma3 = theta3 = vega3 = rho3 = NAN; else if (fabs(vol3 - vol) <= 0.000001) { delta3 = delta; gamma3 = gamma; theta3 = theta; vega3 = vega; rho3 = rho; } else { if (!strcasecmp(type, "C")) bi_amer_call_greeks(spot, strike, r, r, vol3, expiry, steps, &delta3, &gamma3, &theta3, &vega3, &rho3); else bi_amer_put_greeks (spot, strike, r, r, vol3, expiry, steps, &delta3, &gamma3, &theta3, &vega3, &rho3); } strftime(datestr, sizeof datestr, "%F %T", localtime_r(&t, <)); snprintf(res, sizeof res, "GREEKS2,%s.%03d,%s|%.2f,%f,%f,%f,%f,%f,%.2f,%f,%f,%f,%f,%f,%.2f,%f,%f,%f,%f,%f", datestr, atoi(fields[2]), contract, atof(fields[4]), delta, gamma, theta, vega, rho, atof(fields[6]), delta2, gamma2, theta2, vega2, rho2, atof(fields[8]), delta3, gamma3, theta3, vega3, rho3); out2rmp(res); } end: dstr_free_tokens(fields, nfield); return 0; }