You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1968 lines
87 KiB
1968 lines
87 KiB
/******************************************************************************
|
|
* Copyright © 2014-2017 The SuperNET Developers. *
|
|
* *
|
|
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
|
* the top-level directory of this distribution for the individual copyright *
|
|
* holder information and the developer policies on copyright and licensing. *
|
|
* *
|
|
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
|
* SuperNET software, including this file may be copied, modified, propagated *
|
|
* or distributed except according to the terms contained in the LICENSE file *
|
|
* *
|
|
* Removal or modification of this copyright notice is prohibited. *
|
|
* *
|
|
******************************************************************************/
|
|
|
|
#include "../exchanges777.h"
|
|
|
|
#define USD 0
|
|
#define EUR 1
|
|
#define JPY 2
|
|
#define GBP 3
|
|
#define AUD 4
|
|
#define CAD 5
|
|
#define CHF 6
|
|
#define NZD 7
|
|
#define CNY 8
|
|
#define RUB 9
|
|
|
|
#define NZDUSD 0
|
|
#define NZDCHF 1
|
|
#define NZDCAD 2
|
|
#define NZDJPY 3
|
|
#define GBPNZD 4
|
|
#define EURNZD 5
|
|
#define AUDNZD 6
|
|
#define CADJPY 7
|
|
#define CADCHF 8
|
|
#define USDCAD 9
|
|
#define EURCAD 10
|
|
#define GBPCAD 11
|
|
#define AUDCAD 12
|
|
#define USDCHF 13
|
|
#define CHFJPY 14
|
|
#define EURCHF 15
|
|
#define GBPCHF 16
|
|
#define AUDCHF 17
|
|
#define EURUSD 18
|
|
#define EURAUD 19
|
|
#define EURJPY 20
|
|
#define EURGBP 21
|
|
#define GBPUSD 22
|
|
#define GBPJPY 23
|
|
#define GBPAUD 24
|
|
#define USDJPY 25
|
|
#define AUDJPY 26
|
|
#define AUDUSD 27
|
|
|
|
#define USDNUM 28
|
|
#define EURNUM 29
|
|
#define JPYNUM 30
|
|
#define GBPNUM 31
|
|
#define AUDNUM 32
|
|
#define CADNUM 33
|
|
#define CHFNUM 34
|
|
#define NZDNUM 35
|
|
|
|
#define NUM_CONTRACTS 28
|
|
#define NUM_CURRENCIES 8
|
|
#define NUM_COMBINED (NUM_CONTRACTS + NUM_CURRENCIES)
|
|
#define MAX_SPLINES 64
|
|
#define MAX_LOOKAHEAD 72
|
|
#define MAX_CURRENCIES 32
|
|
|
|
#define SATOSHIDEN ((uint64_t)100000000L)
|
|
#define dstr(x) ((double)(x) / SATOSHIDEN)
|
|
#define SMALLVAL 0.000000000000001
|
|
#define PRICE_RESOLUTION_ROOT ((int64_t)3163)
|
|
#define PRICE_RESOLUTION (PRICE_RESOLUTION_ROOT * PRICE_RESOLUTION_ROOT) // 10004569
|
|
#define PRICE_RESOLUTION2 (PRICE_RESOLUTION * PRICE_RESOLUTION) // 100091400875761
|
|
#define PRICE_RESOLUTION_MAXPVAL ((int64_t)3037000500u) // 303.5613528178975 vs 64 bits: 4294967295 429.30058206405493,
|
|
#define PRICE_RESOLUTION_MAXUNITS ((int16_t)((int64_t)0x7fffffffffffffffLLu / (SATOSHIDEN * PRICE_RESOLUTION))) // 9219
|
|
#define SCALED_PRICE(val,scale) (((scale) * (val)) / PRICE_RESOLUTION)
|
|
#define Pval(r) ((double)(r)->Pval / PRICE_RESOLUTION) // for display only!
|
|
#define PERCENTAGE(perc) (((perc) * PRICE_RESOLUTION) / 100)
|
|
|
|
#ifndef MAX
|
|
#define MAX(a,b) ((a) >= (b) ? (a) : (b))
|
|
#endif
|
|
#ifndef MIN
|
|
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
|
#endif
|
|
|
|
struct price_resolution { int64_t Pval; };
|
|
|
|
struct PAX_spline { char name[64]; int32_t splineid,lasti,basenum,num,firstx,dispincr,spline32[MAX_SPLINES][4]; uint32_t utc32[MAX_SPLINES]; int64_t spline64[MAX_SPLINES][4]; double dSplines[MAX_SPLINES][4],pricevals[MAX_SPLINES+MAX_LOOKAHEAD],lastutc,lastval,aveslopeabs; };
|
|
|
|
struct PAX_data
|
|
{
|
|
uint32_t ttimestamps[128]; double tbids[128],tasks[128];
|
|
uint32_t ftimestamps[128]; double fbids[128],fasks[128];
|
|
uint32_t itimestamps[128]; double ibids[128],iasks[128];
|
|
char edate[128]; double ecbmatrix[MAX_CURRENCIES][MAX_CURRENCIES],dailyprices[MAX_CURRENCIES * MAX_CURRENCIES],metals[4];
|
|
uint32_t lastupdate;
|
|
int32_t ecbdatenum,ecbyear,ecbmonth,ecbday; double RTmatrix[MAX_CURRENCIES][MAX_CURRENCIES],RTprices[128],RTmetals[4];
|
|
double basevals[MAX_CURRENCIES],cryptovols[2][9][2],BTCDBTC,BTCUSD,KMDBTC,CNYUSD,btcusd,kmdbtc,cryptos[8];
|
|
struct PAX_spline splines[128];
|
|
};
|
|
|
|
#define _extrapolate_Spline(Splines,gap) ((double)(Splines)[0] + ((gap) * ((double)(Splines)[1] + ((gap) * ((double)(Splines)[2] + ((gap) * (double)(Splines)[3]))))))
|
|
#define _extrapolate_Slope(Splines,gap) ((double)(Splines)[1] + ((gap) * ((double)(Splines)[2] + ((gap) * (double)(Splines)[3]))))
|
|
|
|
#define PRICE_BLEND(oldval,newval,decay,oppodecay) ((oldval == 0.) ? newval : ((oldval * decay) + (oppodecay * newval)))
|
|
#define PRICE_BLEND64(oldval,newval,decay,oppodecay) ((oldval == 0) ? newval : ((oldval * decay) + (oppodecay * newval) + 0.499))
|
|
|
|
#define dto64(x) ((int64_t)((x) * (double)SATOSHIDEN * SATOSHIDEN))
|
|
#define dto32(x) ((int32_t)((x) * (double)SATOSHIDEN))
|
|
#define i64tod(x) ((double)(x) / ((double)SATOSHIDEN * SATOSHIDEN))
|
|
#define i32tod(x) ((double)(x) / (double)SATOSHIDEN)
|
|
#define _extrapolate_spline64(spline64,gap) ((double)i64tod((spline64)[0]) + ((gap) * ((double)i64tod(.001*.001*(spline64)[1]) + ((gap) * ((double)i64tod(.001*.001*.001*.001*(spline64)[2]) + ((gap) * (double)i64tod(.001*.001*.001*.001*.001*.001*(spline64)[3])))))))
|
|
#define _extrapolate_spline32(spline32,gap) ((double)i32tod((spline32)[0]) + ((gap) * ((double)i32tod(.001*.001*(spline32)[1]) + ((gap) * ((double)i32tod(.001*.001*.001*.001*(spline32)[2]) + ((gap) * (double)i32tod(.001*.001*.001*.001*.001*.001*(spline32)[3])))))))
|
|
|
|
int32_t sprimes[168] =
|
|
{
|
|
2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
|
|
31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
|
|
73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
|
|
127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
|
|
179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
|
|
233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
|
|
283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
|
|
353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
|
|
419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
|
|
467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
|
|
547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
|
|
607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
|
|
661, 673, 677, 683, 691, 701, 709, 719, 727, 733,
|
|
739, 743, 751, 757, 761, 769, 773, 787, 797, 809,
|
|
811, 821, 823, 827, 829, 839, 853, 857, 859, 863,
|
|
877, 881, 883, 887, 907, 911, 919, 929, 937, 941,
|
|
947, 953, 967, 971, 977, 983, 991, 997
|
|
};
|
|
|
|
int32_t Peggy_inds[539] = {289, 404, 50, 490, 59, 208, 87, 508, 366, 288, 13, 38, 159, 440, 120, 480, 361, 104, 534, 195, 300, 362, 489, 108, 143, 220, 131, 244, 133, 473, 315, 439, 210, 456, 219, 352, 153, 444, 397, 491, 286, 479, 519, 384, 126, 369, 155, 427, 373, 360, 135, 297, 256, 506, 322, 425, 501, 251, 75, 18, 420, 537, 443, 438, 407, 145, 173, 78, 340, 240, 422, 160, 329, 32, 127, 128, 415, 495, 372, 522, 60, 238, 129, 364, 471, 140, 171, 215, 378, 292, 432, 526, 252, 389, 459, 350, 233, 408, 433, 51, 423, 19, 62, 115, 211, 22, 247, 197, 530, 7, 492, 5, 53, 318, 313, 283, 169, 464, 224, 282, 514, 385, 228, 175, 494, 237, 446, 105, 150, 338, 346, 510, 6, 348, 89, 63, 536, 442, 414, 209, 216, 227, 380, 72, 319, 259, 305, 334, 236, 103, 400, 176, 267, 355, 429, 134, 257, 527, 111, 287, 386, 15, 392, 535, 405, 23, 447, 399, 291, 112, 74, 36, 435, 434, 330, 520, 335, 201, 478, 17, 162, 483, 33, 130, 436, 395, 93, 298, 498, 511, 66, 487, 218, 65, 309, 419, 48, 214, 377, 409, 462, 139, 349, 4, 513, 497, 394, 170, 307, 241, 185, 454, 29, 367, 465, 194, 398, 301, 229, 212, 477, 303, 39, 524, 451, 116, 532, 30, 344, 85, 186, 202, 517, 531, 515, 230, 331, 466, 147, 426, 234, 304, 64, 100, 416, 336, 199, 383, 200, 166, 258, 95, 188, 246, 136, 90, 68, 45, 312, 354, 184, 314, 518, 326, 401, 269, 217, 512, 81, 88, 272, 14, 413, 328, 393, 198, 226, 381, 161, 474, 353, 337, 294, 295, 302, 505, 137, 207, 249, 46, 98, 27, 458, 482, 262, 253, 71, 25, 0, 40, 525, 122, 341, 107, 80, 165, 243, 168, 250, 375, 151, 503, 124, 52, 343, 371, 206, 178, 528, 232, 424, 163, 273, 191, 149, 493, 177, 144, 193, 388, 1, 412, 265, 457, 255, 475, 223, 41, 430, 76, 102, 132, 96, 97, 316, 472, 213, 263, 3, 317, 324, 274, 396, 486, 254, 205, 285, 101, 21, 279, 58, 467, 271, 92, 538, 516, 235, 332, 117, 500, 529, 113, 445, 390, 358, 79, 34, 488, 245, 83, 509, 203, 476, 496, 347, 280, 12, 84, 485, 323, 452, 10, 146, 391, 293, 86, 94, 523, 299, 91, 164, 363, 402, 110, 321, 181, 138, 192, 469, 351, 276, 308, 277, 428, 182, 260, 55, 152, 157, 382, 121, 507, 225, 61, 431, 31, 106, 327, 154, 16, 49, 499, 73, 70, 449, 460, 187, 24, 248, 311, 275, 158, 387, 125, 67, 284, 35, 463, 190, 179, 266, 376, 221, 42, 26, 290, 357, 268, 43, 167, 99, 374, 242, 156, 239, 403, 339, 183, 320, 180, 306, 379, 441, 20, 481, 141, 77, 484, 69, 410, 502, 172, 417, 118, 461, 261, 47, 333, 450, 296, 453, 368, 359, 437, 421, 264, 504, 281, 270, 114, 278, 56, 406, 448, 411, 521, 418, 470, 123, 455, 148, 356, 468, 109, 204, 533, 365, 8, 345, 174, 370, 28, 57, 11, 2, 231, 310, 196, 119, 82, 325, 44, 342, 37, 189, 142, 222, 9, 54, };
|
|
|
|
uint64_t Currencymasks[NUM_CURRENCIES+1];
|
|
|
|
short Contract_base[NUM_COMBINED+1] = { 7, 7, 7, 7, 3, 1, 4, 5, 5, 0, 1, 3, 4, 0, 6, 1, 3, 4, 1, 1, 1, 1, 3, 3, 3, 0, 4, 4, 0,1,2,3,4,5,6,7, 8 };// Contract_base };
|
|
short Contract_rel[NUM_COMBINED+1] = { 0, 6, 5, 2, 7, 7, 7, 2, 6, 5, 5, 5, 5, 6, 2, 6, 6, 6, 0, 4, 2, 3, 0, 2, 4, 2, 2, 0, 0,1,2,3,4,5,6,7,8 };// Contract_rel
|
|
|
|
short Baserel_contractdir[NUM_CURRENCIES+1][NUM_CURRENCIES+1] =
|
|
{
|
|
{ 1, -1, 1, -1, -1, 1, 1, -1, -1 },
|
|
{ 1, 1, 1, 1, 1, 1, 1, 1, -1 },
|
|
{ -1, -1, 1, -1, -1, -1, -1, -1, 0 },
|
|
{ 1, -1, 1, 1, 1, 1, 1, 1, -1 },
|
|
{ 1, -1, 1, -1, 1, 1, 1, 1, -1 },
|
|
{ -1, -1, 1, -1, -1, 1, 1, -1, 0 },
|
|
{ -1, -1, 1, -1, -1, -1, 1, -1, -1 },
|
|
{ 1, -1, 1, -1, -1, 1, 1, 1, 0 },
|
|
{ -1, -1, 0, -1, -1, 0, -1, 0, 1 },
|
|
};
|
|
|
|
short Currency_contracts[NUM_CURRENCIES+1][NUM_CURRENCIES] =
|
|
{
|
|
{ 0, 9, 13, 18, 22, 25, 27, 28, },
|
|
{ 5, 10, 15, 18, 19, 20, 21, 29, },
|
|
{ 3, 7, 14, 20, 23, 25, 26, 30, },
|
|
{ 4, 11, 16, 21, 22, 23, 24, 31, },
|
|
{ 6, 12, 17, 19, 24, 26, 27, 32, },
|
|
{ 2, 7, 8, 9, 10, 11, 12, 33, },
|
|
{ 1, 8, 13, 14, 15, 16, 17, 34, },
|
|
{ 0, 1, 2, 3, 4, 5, 6, 35, },
|
|
{ 36, 37, -1, 38, 39, -1, 40, 41, },
|
|
};
|
|
|
|
short Currency_contractothers[NUM_CURRENCIES+1][NUM_CURRENCIES] = // buggy!
|
|
{
|
|
{ 7, 5, 6, 1, 3, 2, 4, 0, },
|
|
{ 7, 5, 6, 0, 4, 2, 3, 1, },
|
|
{ 7, 5, 6, 1, 3, 0, 4, 2, },
|
|
{ 7, 5, 6, 1, 0, 2, 4, 3, },
|
|
{ 7, 5, 6, 1, 3, 2, 0, 4, },
|
|
{ 7, 2, 6, 0, 1, 3, 4, 5, },
|
|
{ 7, 5, 0, 2, 1, 3, 4, 6, },
|
|
{ 0, 6, 5, 2, 1, 3, 4, 7, },
|
|
{ 0, 1,-1, 3, 4,-1, 5,-1, },
|
|
};
|
|
|
|
short Baserel_contractnum[NUM_CURRENCIES+1][NUM_CURRENCIES+1] =
|
|
{
|
|
{ 28, 18, 25, 22, 27, 9, 13, 0, 36 },
|
|
{ 18, 29, 20, 21, 19, 10, 15, 5, 37 },
|
|
{ 25, 20, 30, 23, 26, 7, 14, 3, -1 },
|
|
{ 22, 21, 23, 31, 24, 11, 16, 4, 38 },
|
|
{ 27, 19, 26, 24, 32, 12, 17, 6, 39 },
|
|
{ 9, 10, 7, 11, 12, 33, 8, 2, -1 },
|
|
{ 13, 15, 14, 16, 17, 8, 34, 1, 40 },
|
|
{ 0, 5, 3, 4, 6, 2, 1, 35, -1 },
|
|
{ 36, 37, -1, 38, 39, -1, 40, -1, 74 },
|
|
};
|
|
|
|
short Currency_contractdirs[NUM_CURRENCIES+1][NUM_CURRENCIES] =
|
|
{
|
|
{ -1, 1, 1, -1, -1, 1, -1, 1 },
|
|
{ 1, 1, 1, 1, 1, 1, 1, 1 },
|
|
{ -1, -1, -1, -1, -1, -1, -1, 1 },
|
|
{ 1, 1, 1, -1, 1, 1, 1, 1 },
|
|
{ 1, 1, 1, -1, -1, 1, 1, 1 },
|
|
{ -1, 1, 1, -1, -1, -1, -1, 1 },
|
|
{ -1, -1, -1, 1, -1, -1, -1, 1 },
|
|
{ 1, 1, 1, 1, -1, -1, -1, 1 },
|
|
{ 1, 1, 1, 1, 1, 1, 1, 1 },
|
|
};
|
|
|
|
char *PAX_bases[64] =
|
|
{
|
|
"KMD", "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", // major currencies
|
|
"CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK",
|
|
"BTCUSD", "NXTBTC", "SuperNET", "ETHBTC", "ETCBTC", "XMRBTC", "KMDBTC", "XCPBTC", // BTC priced
|
|
"XAUUSD", "XAGUSD", "XPTUSD", "XPDUSD", "COPPER", "NGAS", "UKOIL", "USOIL", // USD priced
|
|
"BUND", "NAS100", "SPX500", "US30", "EUSTX50", "UK100", "JPN225", "GER30", "SUI30", "AUS200", "HKG33", "XAUUSD", "BTCRUB", "BTCCNY", "BTCUSD" // abstract
|
|
};
|
|
|
|
uint64_t M1SUPPLY[] = { 3317900000000, 6991604000000, 667780000000000, 1616854000000, 331000000000, 861909000000, 584629000000, 46530000000, // major currencies
|
|
45434000000000, 16827000000000, 3473357229000, 306435000000, 27139000000000, 2150641000000, 347724099000, 1469583000000, 749543000000, 1826110000000, 2400434000000, 1123925000000, 3125276000000, 13975000000000, 317657000000, 759706000000000, 354902000000, 2797061000000, 162189000000, 163745000000, 1712000000000, 39093000000, 1135490000000000, 80317000000,
|
|
100000000 };
|
|
|
|
#define MIND 1000
|
|
uint32_t MINDENOMS[] = { MIND, MIND, 100*MIND, MIND, MIND, MIND, MIND, MIND, // major currencies
|
|
10*MIND, 100*MIND, 10*MIND, MIND, 100*MIND, 10*MIND, MIND, 10*MIND, MIND, 10*MIND, 10*MIND, 10*MIND, 10*MIND, 100*MIND, MIND, 1000*MIND, MIND, 10*MIND, MIND, MIND, 10*MIND, MIND, 10000*MIND, 10*MIND, // end of currencies
|
|
10*MIND,
|
|
};
|
|
|
|
uint64_t komodo_paxvol(uint64_t volume,uint64_t price)
|
|
{
|
|
if ( volume < 10000000000 )
|
|
return((volume * price) / 1000000000);
|
|
else if ( volume < (uint64_t)10 * 10000000000 )
|
|
return((volume * (price / 10)) / 100000000);
|
|
else if ( volume < (uint64_t)100 * 10000000000 )
|
|
return(((volume / 10) * (price / 10)) / 10000000);
|
|
else if ( volume < (uint64_t)1000 * 10000000000 )
|
|
return(((volume / 10) * (price / 100)) / 1000000);
|
|
else if ( volume < (uint64_t)10000 * 10000000000 )
|
|
return(((volume / 100) * (price / 100)) / 100000);
|
|
else if ( volume < (uint64_t)100000 * 10000000000 )
|
|
return(((volume / 100) * (price / 1000)) / 10000);
|
|
else if ( volume < (uint64_t)1000000 * 10000000000 )
|
|
return(((volume / 1000) * (price / 1000)) / 1000);
|
|
else if ( volume < (uint64_t)10000000 * 10000000000 )
|
|
return(((volume / 1000) * (price / 10000)) / 100);
|
|
else return(((volume / 10000) * (price / 10000)) / 10);
|
|
}
|
|
|
|
void pax_rank(uint64_t *ranked,uint32_t *pvals)
|
|
{
|
|
int32_t i; uint64_t vals[32],sum = 0;
|
|
for (i=0; i<32; i++)
|
|
{
|
|
vals[i] = komodo_paxvol(M1SUPPLY[i] / MINDENOMS[i],pvals[i]);
|
|
sum += vals[i];
|
|
}
|
|
for (i=0; i<32; i++)
|
|
{
|
|
ranked[i] = (vals[i] * 1000000000) / sum;
|
|
printf("%.6f ",(double)ranked[i]/1000000000.);
|
|
}
|
|
};
|
|
|
|
#define YAHOO_METALS "XAU", "XAG", "XPT", "XPD"
|
|
static char *Yahoo_metals[] = { YAHOO_METALS };
|
|
|
|
char CURRENCIES[][8] = { "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", // major currencies
|
|
"CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK", // end of currencies
|
|
"XAU", "XAG", "XPT", "XPD", // metals, gold must be first
|
|
"BTCD", "BTC", "NXT", "ETC", "ETH", "KMD", "BTS", "MAID", "XCP", "XMR" // cryptos
|
|
};
|
|
|
|
char CONTRACTS[][16] = { "NZDUSD", "NZDCHF", "NZDCAD", "NZDJPY", "GBPNZD", "EURNZD", "AUDNZD", "CADJPY", "CADCHF", "USDCAD", "EURCAD", "GBPCAD", "AUDCAD", "USDCHF", "CHFJPY", "EURCHF", "GBPCHF", "AUDCHF", "EURUSD", "EURAUD", "EURJPY", "EURGBP", "GBPUSD", "GBPJPY", "GBPAUD", "USDJPY", "AUDJPY", "AUDUSD", "USDCNY", "USDHKD", "USDMXN", "USDZAR", "USDTRY", "EURTRY", "TRYJPY", "USDSGD", "EURNOK", "USDNOK","USDSEK","USDDKK","EURSEK","EURDKK","NOKJPY","SEKJPY","USDPLN","EURPLN","USDILS", // no more currencies
|
|
"XAUUSD", "XAGUSD", "XPTUSD", "XPDUSD", "COPPER", "NGAS", "UKOIL", "USOIL", // commodities
|
|
// cryptos
|
|
"NAS100", "SPX500", "US30", "BUND", "EUSTX50", "UK100", "JPN225", "GER30", "SUI30", "AUS200", "HKG33", "FRA40", "ESP35", "ITA40", "USDOLLAR", // indices
|
|
"SuperNET" // assets
|
|
};
|
|
|
|
int32_t isdecimalstr(char *str)
|
|
{
|
|
int32_t i;
|
|
if ( str == 0 || str[0] == 0 )
|
|
return(0);
|
|
for (i=0; str[i]!=0; i++)
|
|
if ( str[i] < '0' || str[i] > '9' )
|
|
return(0);
|
|
return(i);
|
|
}
|
|
|
|
int32_t PAX_ispair(char *base,char *rel,char *contract)
|
|
{
|
|
int32_t i,j;
|
|
base[0] = rel[0] = 0;
|
|
for (i=0; i<sizeof(CURRENCIES)/sizeof(*CURRENCIES); i++)
|
|
{
|
|
if ( strncmp(CURRENCIES[i],contract,strlen(CURRENCIES[i])) == 0 )
|
|
{
|
|
for (j=0; j<sizeof(CURRENCIES)/sizeof(*CURRENCIES); j++)
|
|
if ( strcmp(CURRENCIES[j],contract+strlen(CURRENCIES[i])) == 0 )
|
|
{
|
|
strcpy(base,CURRENCIES[i]);
|
|
strcpy(rel,CURRENCIES[j]);
|
|
/*USDCNY 6.209700 -> 0.655564
|
|
USDCNY 6.204146 -> 0.652686
|
|
USDHKD 7.753400 -> 0.749321
|
|
USDHKD 7.746396 -> 0.746445
|
|
USDZAR 12.694000 -> 1.101688
|
|
USDZAR 12.682408 -> 1.098811
|
|
USDTRY 2.779700 -> 0.341327
|
|
EURTRY 3.048500 -> 0.386351
|
|
TRYJPY 44.724000 -> 0.690171
|
|
TRYJPY 44.679966 -> 0.687290
|
|
USDSGD 1.375200 -> 0.239415*/
|
|
//if ( strcmp(contract,"USDCNY") == 0 || strcmp(contract,"TRYJPY") == 0 || strcmp(contract,"USDZAR") == 0 )
|
|
// printf("i.%d j.%d base.%s rel.%s\n",i,j,base,rel);
|
|
return((i<<8) | j);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
int32_t PAX_basenum(char *_base)
|
|
{
|
|
int32_t i,j; char base[64];
|
|
strcpy(base,_base);
|
|
touppercase(base);
|
|
if ( 1 )
|
|
{
|
|
for (i=0; i<sizeof(CURRENCIES)/sizeof(*CURRENCIES); i++)
|
|
for (j=0; j<sizeof(CURRENCIES)/sizeof(*CURRENCIES); j++)
|
|
if ( i != j && strcmp(CURRENCIES[i],CURRENCIES[j]) == 0 )
|
|
printf("duplicate.(%s)\n",CURRENCIES[i]);//, getchar();
|
|
}
|
|
for (i=0; i<sizeof(CURRENCIES)/sizeof(*CURRENCIES); i++)
|
|
if ( strcmp(CURRENCIES[i],base) == 0 )
|
|
return(i);
|
|
return(-1);
|
|
}
|
|
|
|
int32_t PAX_contractnum(char *base,char *rel)
|
|
{
|
|
int32_t i,j,c; char contractstr[16],*contract = 0;
|
|
if ( 0 )
|
|
{
|
|
for (i=0; i<sizeof(CONTRACTS)/sizeof(*CONTRACTS); i++)
|
|
for (j=0; j<sizeof(CONTRACTS)/sizeof(*CONTRACTS); j++)
|
|
if ( i != j && strcmp(CONTRACTS[i],CONTRACTS[j]) == 0 )
|
|
printf("duplicate.(%s)\n",CONTRACTS[i]);//, getchar();
|
|
}
|
|
if ( base != 0 && base[0] != 0 && rel != 0 && rel[0] != 0 )
|
|
{
|
|
for (i=0; i<NUM_CURRENCIES; i++)
|
|
if ( strcmp(base,CURRENCIES[i]) == 0 )
|
|
{
|
|
for (j=0; j<NUM_CURRENCIES; j++)
|
|
if ( strcmp(rel,CURRENCIES[j]) == 0 )
|
|
return(Baserel_contractnum[i][j]);
|
|
break;
|
|
}
|
|
sprintf(contractstr,"%s%s",base,rel);
|
|
contract = contractstr;
|
|
} else contract = base;
|
|
if ( contract != 0 && contract[0] != 0 )
|
|
{
|
|
for (c=0; c<sizeof(CONTRACTS)/sizeof(*CONTRACTS); c++)
|
|
if ( strcmp(CONTRACTS[c],contract) == 0 )
|
|
return(c);
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
int32_t PAX_mindenomination(int32_t base)
|
|
{
|
|
return(MINDENOMS[base]);
|
|
}
|
|
|
|
struct price_resolution peggy_scaleprice(struct price_resolution price,int64_t peggymils)
|
|
{
|
|
price.Pval = (10000 * price.Pval) / peggymils;
|
|
return(price);
|
|
}
|
|
|
|
void norm_smooth_wts(int32_t j,double *smoothwts,int32_t n,int32_t numiters)
|
|
{
|
|
double wt; int32_t iter,i;
|
|
for (iter=0; iter<numiters; iter++)
|
|
{
|
|
wt = 0.;
|
|
for (i=0; i<n; i++)
|
|
wt += smoothwts[i];
|
|
//printf("wtsum.j%d %.40f ",j,wt);
|
|
for (i=0; i<n; i++)
|
|
smoothwts[i] /= wt;
|
|
}
|
|
//printf("\n");
|
|
}
|
|
|
|
void calc_smooth_code(int32_t smoothwidth,int32_t _maxprimes)
|
|
{
|
|
double _coeffs[5000],sum,coeffs[60][10000],smoothbuf[10000]; int32_t x,p,prime,numprimes; uint64_t val,isum = 0;
|
|
_maxprimes = MIN((int32_t)(sizeof(coeffs)/(sizeof(double)*10000))-1,_maxprimes);
|
|
smoothwidth = MIN((int32_t)(sizeof(_coeffs)/sizeof(*_coeffs)),smoothwidth);
|
|
x = 5000;
|
|
memset(smoothbuf,0,sizeof(smoothbuf));
|
|
coeffs[0][x-2] = coeffs[0][x] = coeffs[0][x+2] = 1./3.;
|
|
for (numprimes=_maxprimes; numprimes>=3; numprimes--)
|
|
{
|
|
for (p=1; p<numprimes; p++)
|
|
{
|
|
memcpy(coeffs[p],coeffs[p-1],sizeof(coeffs[p]));
|
|
prime = sprimes[p];
|
|
for (x=0; x<10000; x++)
|
|
{
|
|
coeffs[p][x] += (coeffs[p-1][x - prime] / 3.);
|
|
coeffs[p][x] += (coeffs[p-1][x] / 3.);
|
|
coeffs[p][x] += (coeffs[p-1][x + prime] / 3.);
|
|
}
|
|
}
|
|
memcpy(smoothbuf,coeffs[numprimes-1],sizeof(smoothbuf));
|
|
memset(coeffs,0,sizeof(coeffs));
|
|
sum = 0.;
|
|
for (x=0; x<10000; x++)
|
|
{
|
|
if ( smoothbuf[x] != 0. )
|
|
{
|
|
sum += smoothbuf[x];
|
|
//printf("(%d %f) ",x-5000,smoothbuf[x]);
|
|
}
|
|
}
|
|
//printf("maxprimes.%d\n",maxprimes);
|
|
for (x=0; x<10000; x++)
|
|
coeffs[0][x] = (smoothbuf[x] / sum);
|
|
}
|
|
sum = 0.;
|
|
for (x=0; x<10000; x++)
|
|
sum += smoothbuf[x];
|
|
memset(coeffs,0,sizeof(coeffs));
|
|
if ( sum != 0. )
|
|
{
|
|
printf("double Smooth_coeffs[%d] = // numprimes.%d\n{\n",smoothwidth,_maxprimes);
|
|
for (x=0; x<10000; x++)
|
|
{
|
|
if ( smoothbuf[x] != 0. )
|
|
{
|
|
smoothbuf[x] = (1000000. * 1000000. * smoothbuf[x]) / sum;
|
|
//printf("(%d %f) ",x-5000,smoothbuf[x]);
|
|
}
|
|
}
|
|
_coeffs[0] = smoothbuf[5000];
|
|
for (x=1; x<=smoothwidth; x++)
|
|
{
|
|
if ( fabs(smoothbuf[5000 - x] - smoothbuf[5000 + x]) > SMALLVAL )
|
|
printf("x.%d error %.20f != %.20f [%.20f]\n",x,smoothbuf[5000 - x],smoothbuf[5000 + x],smoothbuf[5000 - x] - smoothbuf[5000 + x]);
|
|
_coeffs[x-1] = (smoothbuf[5000 - x] + smoothbuf[5000 + x]) / 2.;
|
|
}
|
|
sum = 0.;
|
|
for (x=0; x<smoothwidth; x++)
|
|
sum += _coeffs[x];
|
|
if ( sum != 0. )
|
|
{
|
|
for (x=0; x<smoothwidth; x++)
|
|
{
|
|
val = ((SATOSHIDEN * 1000. * _coeffs[x] + sum*.4825) / sum);
|
|
printf("%lld, ",(long long)val);
|
|
isum += val;
|
|
//printf("%.0f, ",SATOSHIDEN*1000*_coeffs[x]/sum);
|
|
if ( (x%9) == 8 )
|
|
printf("// x.%d\n",x);
|
|
}
|
|
printf("// isum %lld\n",(long long)isum);
|
|
}
|
|
}
|
|
printf("\n}; // %llu\n",(long long)isum);
|
|
//printf("_Constants size %d\n",(int)__constant_size);
|
|
}
|
|
|
|
uint32_t peggy_mils(int32_t i)
|
|
{
|
|
uint32_t minmils = 0;
|
|
if ( i == 0 )
|
|
return(1000000);
|
|
else if ( i <= MAX_CURRENCIES )
|
|
minmils = 10 * PAX_mindenomination(i-1);
|
|
else if ( i >= 64 )
|
|
return(10000);
|
|
else if ( PAX_bases[i] != 0 )
|
|
{
|
|
if ( isdecimalstr(PAX_bases[i]+strlen(PAX_bases[i])-2) != 0 || strcmp(PAX_bases[i],"BTCRUB") == 0 )
|
|
minmils = 1;
|
|
else if ( strncmp(PAX_bases[i],"XAU",3) == 0 || strcmp(PAX_bases[i],"BTCCNY") == 0 || strcmp(PAX_bases[i],"BTCUSD") == 0 || strncmp(PAX_bases[i],"XPD",3) == 0 || strncmp(PAX_bases[i],"XPT",3) == 0 )
|
|
minmils = 10;
|
|
else if ( strcmp(PAX_bases[i],"BUND") == 0 || strcmp(PAX_bases[i],"UKOIL") == 0 || strcmp(PAX_bases[i],"USOIL") == 0 )
|
|
minmils = 100;
|
|
else if ( strncmp(PAX_bases[i],"ETC",3) == 0 || strcmp(PAX_bases[i],"SuperNET") == 0 || strncmp(PAX_bases[i],"XAG",3) == 0 || strncmp(PAX_bases[i],"ETH",3) == 0 || strncmp(PAX_bases[i],"XCP",3) == 0 )
|
|
minmils = 1000;
|
|
else if ( strncmp(PAX_bases[i],"XMR",3) == 0 )
|
|
minmils = 10000;
|
|
else if ( strncmp(PAX_bases[i],"NXT",3) == 0 || strncmp(PAX_bases[i],"BTS",3) == 0 )
|
|
minmils = 1000000;
|
|
else if ( strncmp(PAX_bases[i],"KMD",5) == 0 )
|
|
minmils = 1000;
|
|
else minmils = 10000;
|
|
}
|
|
return(minmils);
|
|
}
|
|
|
|
int32_t peggy_prices(struct price_resolution prices[64],double btcusd,double kmdbtc,char *contracts[],int32_t num,double *cprices,double *basevals)
|
|
{
|
|
double kmdusd,price_in_kmd,dprice,usdcny,usdrub,btccny,btcrub,xauusd,usdprice=0.,usdval,btcprice=0.; int32_t contractnum,base,nonz = 0;
|
|
if ( btcusd > SMALLVAL && (usdval= basevals[0]) > SMALLVAL )
|
|
{
|
|
xauusd = usdcny = usdrub = btccny = btcrub = 0.;
|
|
for (contractnum=0; contractnum<num; contractnum++)
|
|
if ( strcmp(contracts[contractnum],"XAUUSD") == 0 )
|
|
{
|
|
xauusd = cprices[contractnum];
|
|
break;
|
|
}
|
|
if ( basevals[8] > SMALLVAL )
|
|
{
|
|
usdcny = (basevals[0] * peggy_mils(8)) / (basevals[8] * peggy_mils(0));
|
|
btccny = 1000 * btcusd * usdcny;
|
|
}
|
|
if ( basevals[9] > SMALLVAL )
|
|
{
|
|
usdrub = (basevals[0] * peggy_mils(9)) / (basevals[9] * peggy_mils(0));
|
|
btcrub = 1000 * btcusd * usdrub;
|
|
}
|
|
if ( kmdbtc < SMALLVAL )
|
|
kmdbtc = 0.0001;
|
|
kmdusd = (btcusd * kmdbtc);
|
|
printf("xauusd %f usdval %f %f %f usdcny %f usdrub %f btcusd %f kmdbtc %f kmdusd %f btccny %f btcrub %f\n",xauusd,usdval,basevals[8],basevals[9],usdcny,usdrub,btcusd,kmdbtc,kmdusd,btccny,btcrub);
|
|
prices[0].Pval = (PRICE_RESOLUTION * 100. * kmdbtc);
|
|
for (base=0,contractnum=1; base<32; base++,contractnum++)
|
|
{
|
|
if ( strcmp(contracts[contractnum],CURRENCIES[base]) == 0 )
|
|
{
|
|
if ( (dprice= basevals[base]) > SMALLVAL )
|
|
{
|
|
nonz++;
|
|
if ( base == 0 )
|
|
usdprice = price_in_kmd = (1. / kmdusd);
|
|
else price_in_kmd = (dprice / (kmdusd * usdval));
|
|
prices[contractnum].Pval = (PRICE_RESOLUTION * price_in_kmd);
|
|
}
|
|
} else printf("unexpected list entry %s vs %s at %d\n",contracts[contractnum],CURRENCIES[base],contractnum);
|
|
}
|
|
if ( strcmp(contracts[contractnum],"BTCUSD") != 0 )
|
|
printf("unexpected contract (%s) at %d\n",contracts[contractnum],contractnum);
|
|
btcprice = (1. / kmdbtc);
|
|
prices[contractnum++].Pval = (PRICE_RESOLUTION / kmdbtc) / 1000.;
|
|
printf("btcprice %f = 1/%f %llu\n",btcprice,1./kmdbtc,(long long)prices[contractnum-1].Pval);
|
|
for (; contractnum<64; contractnum++)
|
|
{
|
|
//dprice = 0;
|
|
if ( contractnum == 63 && strcmp(contracts[contractnum],"BTCUSD") == 0 )
|
|
dprice = btcusd;
|
|
else if ( contractnum == 62 && strcmp(contracts[contractnum],"BTCCNY") == 0 )
|
|
dprice = btccny;
|
|
else if ( contractnum == 61 && strcmp(contracts[contractnum],"BTCRUB") == 0 )
|
|
dprice = btcrub;
|
|
else if ( contractnum == 60 && strcmp(contracts[contractnum],"XAUUSD") == 0 )
|
|
dprice = xauusd;
|
|
else
|
|
{
|
|
dprice = cprices[contractnum];
|
|
if ( dprice > SMALLVAL && strlen(contracts[contractnum]) > 3 )
|
|
{
|
|
if ( strcmp(contracts[contractnum]+strlen(contracts[contractnum])-3,"USD") == 0 || strcmp(contracts[contractnum],"COPPER") == 0 || strcmp(contracts[contractnum],"NGAS") == 0 || strcmp(contracts[contractnum],"UKOIL") == 0 || strcmp(contracts[contractnum],"USOIL") == 0 )
|
|
dprice *= usdprice;
|
|
else if ( strcmp(contracts[contractnum],"SuperNET") == 0 )
|
|
{
|
|
printf("SuperNET %f -> %f\n",dprice,dprice*btcprice);
|
|
dprice *= btcprice;
|
|
}
|
|
else if ( strcmp(contracts[contractnum]+strlen(contracts[contractnum])-3,"BTC") == 0 )
|
|
dprice *= btcprice;
|
|
}
|
|
}
|
|
prices[contractnum].Pval = (uint64_t)((PRICE_RESOLUTION * dprice) * ((double)peggy_mils(contractnum) / 10000.));
|
|
//if ( Debuglevel > 2 )
|
|
{
|
|
struct price_resolution tmp;
|
|
tmp = peggy_scaleprice(prices[contractnum],peggy_mils(contractnum));
|
|
printf("%.8f btcprice %.6f %f -->>> %s %.6f -> %llu %.6f mils.%d\n",cprices[contractnum],btcprice,cprices[contractnum]*btcprice,contracts[contractnum],Pval(&tmp),(long long)prices[contractnum].Pval,Pval(&prices[contractnum]),peggy_mils(contractnum));
|
|
}
|
|
}
|
|
}
|
|
return(nonz);
|
|
}
|
|
|
|
void init_Currencymasks()
|
|
{
|
|
int32_t base,j,c; uint64_t basemask;
|
|
for (base=0; base<NUM_CURRENCIES; base++)
|
|
{
|
|
basemask = 0L;
|
|
for (j=0; j<7; j++)
|
|
{
|
|
if ( (c= Currency_contracts[base][j]) >= 0 )
|
|
{
|
|
basemask |= (1L << c);
|
|
//printf("(%s %lx) ",CONTRACTS[c],1L<<c);
|
|
}
|
|
}
|
|
Currencymasks[base] = basemask;
|
|
printf("0x%llx, ",(long long)basemask);
|
|
}
|
|
}
|
|
|
|
double calc_primary_currencies(double logmatrix[8][8],double *bids,double *asks)
|
|
{
|
|
uint64_t nonzmask; int32_t c,base,rel; double bid,ask;
|
|
memset(logmatrix,0,sizeof(double)*8*8);
|
|
nonzmask = 0;
|
|
for (c=0; c<28; c++)
|
|
{
|
|
bid = bids[c];
|
|
ask = asks[c];
|
|
if ( bid != 0 && ask != 0 )
|
|
{
|
|
base = Contract_base[c];
|
|
rel = Contract_rel[c];
|
|
nonzmask |= (1L << c);
|
|
logmatrix[base][rel] = log(bid);
|
|
logmatrix[rel][base] = -log(ask);
|
|
//printf("[%f %f] ",bid,ask);
|
|
}
|
|
}
|
|
//printf("%07lx\n",nonzmask);
|
|
if ( nonzmask != 0 )
|
|
{
|
|
bids[USDNUM] = (logmatrix[USD][EUR] + logmatrix[USD][JPY] + logmatrix[USD][GBP] + logmatrix[USD][AUD] + logmatrix[USD][CAD] + logmatrix[USD][CHF] + logmatrix[USD][NZD]) / 8.;
|
|
asks[USDNUM] = -(logmatrix[EUR][USD] + logmatrix[JPY][USD] + logmatrix[GBP][USD] + logmatrix[AUD][USD] + logmatrix[CAD][USD] + logmatrix[CHF][USD] + logmatrix[NZD][USD]) / 8.;
|
|
|
|
bids[EURNUM] = (logmatrix[EUR][USD] + logmatrix[EUR][JPY] + logmatrix[EUR][GBP] + logmatrix[EUR][AUD] + logmatrix[EUR][CAD] + logmatrix[EUR][CHF] + logmatrix[EUR][NZD]) / 8.;
|
|
asks[EURNUM] = -(logmatrix[USD][EUR] + logmatrix[JPY][EUR] + logmatrix[GBP][EUR] + logmatrix[AUD][EUR] + logmatrix[CAD][EUR] + logmatrix[CHF][EUR] + logmatrix[NZD][EUR]) / 8.;
|
|
|
|
bids[JPYNUM] = (logmatrix[JPY][USD] + logmatrix[JPY][EUR] + logmatrix[JPY][GBP] + logmatrix[JPY][AUD] + logmatrix[JPY][CAD] + logmatrix[JPY][CHF] + logmatrix[JPY][NZD]) / 8.;
|
|
asks[JPYNUM] = -(logmatrix[USD][JPY] + logmatrix[EUR][JPY] + logmatrix[GBP][JPY] + logmatrix[AUD][JPY] + logmatrix[CAD][JPY] + logmatrix[CHF][JPY] + logmatrix[NZD][JPY]) / 8.;
|
|
|
|
bids[GBPNUM] = (logmatrix[GBP][USD] + logmatrix[GBP][EUR] + logmatrix[GBP][JPY] + logmatrix[GBP][AUD] + logmatrix[GBP][CAD] + logmatrix[GBP][CHF] + logmatrix[GBP][NZD]) / 8.;
|
|
asks[GBPNUM] = -(logmatrix[USD][GBP] + logmatrix[EUR][GBP] + logmatrix[JPY][GBP] + logmatrix[AUD][GBP] + logmatrix[CAD][GBP] + logmatrix[CHF][GBP] + logmatrix[NZD][GBP]) / 8.;
|
|
|
|
bids[AUDNUM] = (logmatrix[AUD][USD] + logmatrix[AUD][EUR] + logmatrix[AUD][JPY] + logmatrix[AUD][GBP] + logmatrix[AUD][CAD] + logmatrix[AUD][CHF] + logmatrix[AUD][NZD]) / 8.;
|
|
asks[AUDNUM] = -(logmatrix[USD][AUD] + logmatrix[EUR][AUD] + logmatrix[JPY][AUD] + logmatrix[GBP][AUD] + logmatrix[CAD][AUD] + logmatrix[CHF][AUD] + logmatrix[NZD][AUD]) / 8.;
|
|
|
|
bids[CADNUM] = (logmatrix[CAD][USD] + logmatrix[CAD][EUR] + logmatrix[CAD][JPY] + logmatrix[CAD][GBP] + logmatrix[CAD][AUD] + logmatrix[CAD][CHF] + logmatrix[CAD][NZD]) / 8.;
|
|
asks[CADNUM] = -(logmatrix[USD][CAD] + logmatrix[EUR][CAD] + logmatrix[JPY][CAD] + logmatrix[GBP][CAD] + logmatrix[AUD][CAD] + logmatrix[CHF][CAD] + logmatrix[NZD][CAD]) / 8.;
|
|
|
|
bids[CHFNUM] = (logmatrix[CHF][USD] + logmatrix[CHF][EUR] + logmatrix[CHF][JPY] + logmatrix[CHF][GBP] + logmatrix[CHF][AUD] + logmatrix[CHF][CAD] + logmatrix[CHF][NZD]) / 8.;
|
|
asks[CHFNUM] = -(logmatrix[USD][CHF] + logmatrix[EUR][CHF] + logmatrix[JPY][CHF] + logmatrix[GBP][CHF] + logmatrix[AUD][CHF] + logmatrix[CAD][CHF] + logmatrix[NZD][CHF]) / 8.;
|
|
|
|
bids[NZDNUM] = (logmatrix[NZD][USD] + logmatrix[NZD][EUR] + logmatrix[NZD][JPY] + logmatrix[NZD][GBP] + logmatrix[NZD][AUD] + logmatrix[NZD][CAD] + logmatrix[NZD][CHF]) / 8.;
|
|
asks[NZDNUM] = -(logmatrix[USD][NZD] + logmatrix[EUR][NZD] + logmatrix[JPY][NZD] + logmatrix[GBP][NZD] + logmatrix[AUD][NZD] + logmatrix[CAD][NZD] + logmatrix[CHF][NZD]) / 8.;
|
|
if ( nonzmask != ((1<<28)-1) )
|
|
{
|
|
for (base=0; base<8; base++)
|
|
{
|
|
if ( (nonzmask & Currencymasks[base]) != Currencymasks[base] )
|
|
bids[base+28] = asks[base+28] = 0;
|
|
//else printf("%s %9.6f | ",CONTRACTS[base+28],_pairaved(bids[base+28],asks[base+28]));
|
|
}
|
|
//printf("keep.%07lx\n",nonzmask);
|
|
return(0);
|
|
}
|
|
if ( 0 && nonzmask != 0 )
|
|
{
|
|
for (base=0; base<8; base++)
|
|
printf("%9.6f | ",_pairaved(bids[base+28],asks[base+28]));
|
|
printf("%07llx\n",(long long)nonzmask);
|
|
}
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
double PAX_splineval(struct PAX_spline *spline,uint32_t timestamp,int32_t lookahead)
|
|
{
|
|
int32_t i,gap,ind = (spline->num - 1);
|
|
if ( timestamp >= spline->utc32[ind] )
|
|
{
|
|
gap = (timestamp - spline->utc32[ind]);
|
|
if ( gap < lookahead )
|
|
return(_extrapolate_spline64(spline->spline64[ind],gap));
|
|
else return(0.);
|
|
}
|
|
else if ( timestamp <= spline->utc32[0] )
|
|
{
|
|
gap = (spline->utc32[0] - timestamp);
|
|
if ( gap < lookahead )
|
|
return(_extrapolate_spline64(spline->spline64[0],gap));
|
|
else return(0.);
|
|
}
|
|
for (i=0; i<spline->num-1; i++)
|
|
{
|
|
ind = (i + spline->lasti) % (spline->num - 1);
|
|
if ( timestamp >= spline->utc32[ind] && timestamp < spline->utc32[ind+1] )
|
|
{
|
|
spline->lasti = ind;
|
|
return(_extrapolate_spline64(spline->spline64[ind],timestamp - spline->utc32[ind]));
|
|
}
|
|
}
|
|
return(0.);
|
|
}
|
|
|
|
double PAX_calcspline(struct PAX_spline *spline,double *outputs,double *slopes,int32_t dispwidth,uint32_t *utc32,double *splinevals,int32_t num)
|
|
{
|
|
static double errsums[3]; static int errcount;
|
|
double c[MAX_SPLINES],f[MAX_SPLINES],dd[MAX_SPLINES],dl[MAX_SPLINES],du[MAX_SPLINES],gaps[MAX_SPLINES];
|
|
int32_t n,i,lasti,x,numsplines,nonz; double vx,vy,vw,vz,gap,sum,xval,yval,abssum,lastval,lastxval,yval64,yval32,yval3; uint32_t gap32;
|
|
sum = lastxval = n = lasti = nonz = 0;
|
|
for (i=0; i<MAX_SPLINES&&i<num; i++)
|
|
{
|
|
if ( (f[n]= splinevals[i]) != 0. && utc32[i] != 0 )
|
|
{
|
|
//printf("i%d.(%u %f) ",i,utc32[i],splinevals[i]);
|
|
//printf("%f ",splinevals[i]);
|
|
if ( n > 0 )
|
|
{
|
|
if ( (gaps[n-1]= utc32[i] - lastxval) < 0 )
|
|
{
|
|
printf("illegal gap %f to t%d\n",lastxval,utc32[i]);
|
|
return(0);
|
|
}
|
|
}
|
|
spline->utc32[n] = lastxval = utc32[i];
|
|
n++;
|
|
}
|
|
}
|
|
if ( (numsplines= n) < 4 )
|
|
return(0);
|
|
for (i=0; i<n-3; i++)
|
|
dl[i] = du[i] = gaps[i+1];
|
|
for (i=0; i<n-2; i++)
|
|
{
|
|
dd[i] = 2.0 * (gaps[i] + gaps[i+1]);
|
|
c[i] = (3.0 / (double)gaps[i+1]) * (f[i+2] - f[i+1]) - (3.0 / (double)gaps[i]) * (f[i+1] - f[i]);
|
|
}
|
|
//for (i=0; i<n; i++)
|
|
// printf("%f ",f[i]);
|
|
//printf("F2[%d]\n",n);
|
|
dd[0] += (gaps[0] + (double)gaps[0]*gaps[0] / gaps[1]);
|
|
du[0] -= ((double)gaps[0]*gaps[0] / gaps[1]);
|
|
dd[n-3] += (gaps[n-2] + (double)gaps[n-2]*gaps[n-2] / gaps[n-3]);
|
|
dl[n-4] -= ((double)gaps[n-2]*gaps[n-2] / gaps[n-3]);
|
|
|
|
//tridiagonal(n-2, dl, dd, du, c);
|
|
for (i=0; i<n-1-2; i++)
|
|
{
|
|
du[i] /= dd[i];
|
|
dd[i+1] -= dl[i]*du[i];
|
|
}
|
|
c[0] /= dd[0];
|
|
for (i=1; i<n-2; i++)
|
|
c[i] = (c[i] - dl[i-1] * c[i-1]) / dd[i];
|
|
for (i=n-2-4; i>=0; i--)
|
|
c[i] -= c[i+1] * du[i];
|
|
//tridiagonal(n-2, dl, dd, du, c);
|
|
|
|
for (i=n-3; i>=0; i--)
|
|
c[i+1] = c[i];
|
|
c[0] = (1.0 + (double)gaps[0] / gaps[1]) * c[1] - ((double)gaps[0] / gaps[1] * c[2]);
|
|
c[n-1] = (1.0 + (double)gaps[n-2] / gaps[n-3] ) * c[n-2] - ((double)gaps[n-2] / gaps[n-3] * c[n-3]);
|
|
//printf("c[n-1] %f, n-2 %f, n-3 %f\n",c[n-1],c[n-2],c[n-3]);
|
|
abssum = nonz = lastval = 0;
|
|
outputs[spline->firstx] = f[0];
|
|
spline->num = numsplines;
|
|
for (i=0; i<n; i++)
|
|
{
|
|
vx = f[i];
|
|
vz = c[i];
|
|
if ( i < n-1 )
|
|
{
|
|
gap = gaps[i];
|
|
vy = ((f[i+1] - f[i]) / gap) - (gap * (c[i+1] + 2.*c[i]) / 3.);
|
|
vw = (c[i+1] - c[i]) / (3. * gap);
|
|
}
|
|
else
|
|
{
|
|
vy = 0;
|
|
vw = 0;
|
|
}
|
|
//printf("%3d: t%u [%14.11f %14.11f %14.11f %14.11f] gap %f | %d\n",i,spline->utc32[i],(vx),vy*1000*1000,vz*1000*1000*1000*1000,vw*1000*1000*1000*1000*1000*1000,gap,conv_unixtime(&tmp,spline->utc32[i]));
|
|
spline->dSplines[i][0] = vx, spline->dSplines[i][1] = vy, spline->dSplines[i][2] = vz, spline->dSplines[i][3] = vw;
|
|
spline->spline64[i][0] = dto64(vx), spline->spline64[i][1] = dto64(vy*1000*1000), spline->spline64[i][2] = dto64(vz*1000*1000*1000*1000), spline->spline64[i][3] = dto64(vw*1000*1000*1000*1000*1000*1000);
|
|
spline->spline32[i][0] = dto32(vx), spline->spline32[i][1] = dto32(vy*1000*1000), spline->spline32[i][2] = dto32(vz*1000*1000*1000*1000), spline->spline32[i][3] = dto32(vw*1000*1000*1000*1000*1000*1000);
|
|
gap32 = gap = spline->dispincr;
|
|
xval = spline->utc32[i] + gap;
|
|
lastval = vx;
|
|
while ( i < n-1 )
|
|
{
|
|
x = spline->firstx + ((xval - spline->utc32[0]) / spline->dispincr);
|
|
if ( x > dispwidth-1 ) x = dispwidth-1;
|
|
if ( x < 0 ) x = 0;
|
|
if ( (i < n-2 && gap > gaps[i] + spline->dispincr) )
|
|
break;
|
|
if ( i == n-2 && xval > spline->utc32[n-1] + MAX_LOOKAHEAD*spline->dispincr )
|
|
{
|
|
//printf("x.%d dispwidth.%d xval %f > utc[n-1] %f + %f\n",x,dispwidth,xval,utc[n-1],MAX_LOOKAHEAD*incr);
|
|
break;
|
|
}
|
|
if ( x >= 0 )
|
|
{
|
|
yval = _extrapolate_Spline(spline->dSplines[i],gap);
|
|
yval64 = _extrapolate_spline64(spline->spline64[i],gap32);
|
|
if ( (yval3 = PAX_splineval(spline,gap32 + spline->utc32[i],MAX_LOOKAHEAD*spline->dispincr)) != 0 )
|
|
{
|
|
yval32 = _extrapolate_spline32(spline->spline32[i],gap32);
|
|
errsums[0] += fabs(yval - yval64), errsums[1] += fabs(yval - yval32), errsums[2] += fabs(yval - yval3), errcount++;
|
|
if ( fabs(yval - yval3) > SMALLVAL )
|
|
printf("(%.10f vs %.10f %.10f %.10f [%.16f %.16f %.16f]) ",yval,yval64,yval32,yval3, errsums[0]/errcount,errsums[1]/errcount,errsums[2]/errcount);
|
|
}
|
|
if ( yval > 5000. ) yval = 5000.;
|
|
else if ( yval < -5000. ) yval = -5000.;
|
|
if ( isnan(yval) == 0 )
|
|
{
|
|
outputs[x] = yval;
|
|
spline->lastval = outputs[x], spline->lastutc = xval;
|
|
if ( 1 && fabs(lastval) > SMALLVAL )
|
|
{
|
|
if ( lastval != 0 && outputs[x] != 0 )
|
|
{
|
|
if ( slopes != 0 )
|
|
slopes[x] = (outputs[x] - lastval), abssum += fabs(slopes[x]);
|
|
nonz++;
|
|
}
|
|
}
|
|
}
|
|
//else outputs[x] = 0.;
|
|
//printf("x.%-4d %d %f %f %f i%-4d: gap %9.6f %9.6f last %9.6f slope %9.6f | %9.1f [%9.1f %9.6f %9.6f %9.6f %9.6f]\n",x,firstx,xval,utc[0],incr,i,gap,yval,lastval,slopes[x],xval,utc[i+1],dSplines[i][0],dSplines[i][1]*1000*1000,dSplines[i][2]*1000*1000*1000*1000,dSplines[i][3]*1000*1000*1000*1000*1000*1000);
|
|
}
|
|
gap32 += spline->dispincr, gap += spline->dispincr, xval += spline->dispincr;
|
|
}
|
|
//double pred = (i>0) ? _extrapolate_Spline(dSplines[i-1],gaps[i-1]) : 0.;
|
|
//printf("%2d: w%8.1f [gap %f -> %9.6f | %9.6f %9.6f %9.6f %9.6f %9.6f]\n",i,weekinds[i],gap,pred,f[i],dSplines[i].x,1000000*dSplines[i].y,1000000*1000000*dSplines[i].z,1000000*1000000*1000*dSplines[i].w);
|
|
}
|
|
if ( nonz != 0 )
|
|
abssum /= nonz;
|
|
spline->aveslopeabs = abssum;
|
|
return(lastval);
|
|
}
|
|
|
|
int32_t PAX_genspline(struct PAX_spline *spline,int32_t splineid,char *name,uint32_t *utc32,double *splinevals,int32_t maxsplines,double *refvals)
|
|
{
|
|
int32_t i; double output[2048],slopes[2048],origvals[MAX_SPLINES];
|
|
memset(spline,0,sizeof(*spline)), memset(output,0,sizeof(output)), memset(slopes,0,sizeof(slopes));
|
|
spline->dispincr = 3600, spline->basenum = splineid, strcpy(spline->name,name);
|
|
memcpy(origvals,splinevals,sizeof(*splinevals) * MAX_SPLINES);
|
|
spline->lastval = PAX_calcspline(spline,output,slopes,sizeof(output)/sizeof(*output),utc32,splinevals,maxsplines);
|
|
for (i=0; i<spline->num; i++)
|
|
{
|
|
if ( i < spline->num )
|
|
{
|
|
if ( 0 && refvals[i] != 0 && output[i * 24] != refvals[i] )
|
|
printf("{%.8f != %.8f}.%d ",output[i * 24],refvals[i],i);
|
|
spline->pricevals[i] = output[i * 24];
|
|
}
|
|
}
|
|
//printf("spline.%s num.%d\n",name,spline->num);
|
|
return(spline->num);
|
|
}
|
|
|
|
int32_t PAX_calcmatrix(double matrix[MAX_CURRENCIES][MAX_CURRENCIES])
|
|
{
|
|
int32_t basenum,relnum,nonz,vnum,iter,numbase,numerrs = 0; double sum,vsum,price,price2,basevals[32],errsum=0;
|
|
memset(basevals,0,sizeof(basevals));
|
|
for (iter=0; iter<2; iter++)
|
|
{
|
|
numbase = MAX_CURRENCIES;
|
|
for (basenum=0; basenum<numbase; basenum++)
|
|
{
|
|
for (vsum=sum=vnum=nonz=relnum=0; relnum<numbase; relnum++)
|
|
{
|
|
if ( basenum != relnum )
|
|
{
|
|
if ( (price= matrix[basenum][relnum]) != 0. )
|
|
{
|
|
price /= (MINDENOMS[relnum] * .001);
|
|
price *= (MINDENOMS[basenum] * .001);
|
|
if ( iter == 0 )
|
|
sum += (price), nonz++;//, printf("%.8f ",price);
|
|
else sum += fabs((price) - (basevals[basenum] / basevals[relnum])), nonz++;
|
|
}
|
|
if ( (price2= matrix[relnum][basenum]) != 0. )
|
|
{
|
|
price2 *= (MINDENOMS[relnum] * .001);
|
|
price2 /= (MINDENOMS[basenum] * .001);
|
|
if ( iter == 0 )
|
|
vsum += (price2), vnum++;
|
|
else vsum += fabs(price2 - (basevals[relnum] / basevals[basenum])), vnum++;
|
|
}
|
|
//if ( iter == 0 && 1/price2 > price )
|
|
// printf("base.%d rel.%d price2 %f vs %f\n",basenum,relnum,1/price2,price);
|
|
}
|
|
}
|
|
if ( iter == 0 )
|
|
sum += 1., vsum += 1.;
|
|
if ( nonz != 0 )
|
|
sum /= nonz;
|
|
if ( vnum != 0 )
|
|
vsum /= vnum;
|
|
if ( iter == 0 )
|
|
basevals[basenum] = (sum + 1./vsum) / 2.;
|
|
else errsum += (sum + vsum)/2, numerrs++;//, printf("(%.8f %.8f) ",sum,vsum);
|
|
//printf("date.%d (%.8f/%d %.8f/%d).%02d -> %.8f\n",i,sum,nonz,vsum,vnum,basenum,basevals[basenum]);
|
|
}
|
|
if ( iter == 0 )
|
|
{
|
|
for (sum=relnum=0; relnum<numbase; relnum++)
|
|
sum += (basevals[relnum]);//, printf("%.8f ",(basevals[relnum]));
|
|
//printf("date.%d sums %.8f and vsums iter.%d\n",relnum,sum/7,iter);
|
|
sum /= (numbase - 1);
|
|
for (relnum=0; relnum<numbase; relnum++)
|
|
basevals[relnum] /= sum;//, printf("%.8f ",basevals[relnum]);
|
|
//printf("date.%d sums %.8f and vsums iter.%d\n",i,sum,iter);
|
|
}
|
|
else
|
|
{
|
|
for (basenum=0; basenum<numbase; basenum++)
|
|
matrix[basenum][basenum] = basevals[basenum];
|
|
}
|
|
}
|
|
if ( numerrs != 0 )
|
|
errsum /= numerrs;
|
|
return(errsum);
|
|
}
|
|
|
|
int32_t PAX_getmatrix(double *basevals,struct PAX_data *dp,double Hmatrix[32][32],double *RTprices,char *contracts[],int32_t num)
|
|
{
|
|
int32_t i,j,c; char name[16]; double btcusd,kmdbtc;
|
|
memcpy(Hmatrix,dp->ecbmatrix,sizeof(dp->ecbmatrix));
|
|
PAX_calcmatrix(Hmatrix);
|
|
/*for (i=0; i<32; i++)
|
|
{
|
|
for (j=0; j<32; j++)
|
|
printf("%.6f ",Hmatrix[i][j]);
|
|
printf("%s\n",CURRENCIES[i]);
|
|
}*/
|
|
btcusd = dp->btcusd;
|
|
kmdbtc = dp->kmdbtc;
|
|
if ( btcusd > SMALLVAL )
|
|
dxblend(&dp->BTCUSD,btcusd,.9);
|
|
if ( kmdbtc > SMALLVAL )
|
|
dxblend(&dp->KMDBTC,kmdbtc,.9);
|
|
// char *cryptostrs[8] = { "btc", "nxt", "unity", "eth", "ltc", "xmr", "bts", "xcp" };
|
|
// "BTCUSD", "NXTBTC", "SuperNET", "ETHBTC", "ETCBTC", "XMRBTC", "KMDBTC", "XCPBTC", // BTC priced
|
|
for (i=0; i<num; i++)
|
|
{
|
|
if ( contracts[i] == 0 )
|
|
continue;
|
|
if ( i == num-1 && strcmp(contracts[i],"BTCUSD") == 0 )
|
|
{
|
|
RTprices[i] = dp->BTCUSD;
|
|
continue;
|
|
}
|
|
else if ( i == num-2 && strcmp(contracts[i],"BTCCNY") == 0 )
|
|
{
|
|
continue;
|
|
}
|
|
else if ( i == num-3 && strcmp(contracts[i],"BTCRUB") == 0 )
|
|
{
|
|
continue;
|
|
}
|
|
else if ( i == num-4 && strcmp(contracts[i],"XAUUSD") == 0 )
|
|
{
|
|
continue;
|
|
}
|
|
if ( strcmp(contracts[i],"NXTBTC") == 0 )
|
|
RTprices[i] = dp->cryptos[1];
|
|
else if ( strcmp(contracts[i],"SuperNET") == 0 )
|
|
RTprices[i] = dp->cryptos[2];
|
|
else if ( strcmp(contracts[i],"ETHBTC") == 0 )
|
|
RTprices[i] = dp->cryptos[3];
|
|
else if ( strcmp(contracts[i],"ETCBTC") == 0 )
|
|
RTprices[i] = dp->cryptos[4];
|
|
else if ( strcmp(contracts[i],"XMRBTC") == 0 )
|
|
RTprices[i] = dp->cryptos[5];
|
|
else if ( strcmp(contracts[i],"KMDBTC") == 0 )
|
|
RTprices[i] = dp->cryptos[6];
|
|
else if ( strcmp(contracts[i],"XCPBTC") == 0 )
|
|
RTprices[i] = dp->cryptos[7];
|
|
else if ( i < MAX_CURRENCIES )
|
|
{
|
|
dp->RTmatrix[i][i] = basevals[i] = Hmatrix[i][i];
|
|
//if ( Debuglevel > 2 )
|
|
//printf("(%s %f).%d ",CURRENCIES[i],basevals[i],i);
|
|
}
|
|
else if ( (c= PAX_contractnum(contracts[i],0)) >= 0 )
|
|
{
|
|
RTprices[i] = dp->RTprices[c];
|
|
//if ( isdecimalstr(contracts[i]+strlen(contracts[i])-2) != 0 )
|
|
// cprices[i] *= .0001;
|
|
}
|
|
else
|
|
{
|
|
for (j=0; j<sizeof(Yahoo_metals)/sizeof(*Yahoo_metals); j++)
|
|
{
|
|
sprintf(name,"%sUSD",Yahoo_metals[j]);
|
|
if ( contracts[i] != 0 && strcmp(name,contracts[i]) == 0 )
|
|
{
|
|
RTprices[i] = dp->RTmetals[j];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if ( Debuglevel > 2 )
|
|
printf("(%f %f) i.%d num.%d %s %f\n",dp->BTCUSD,dp->KMDBTC,i,num,contracts[i],RTprices[i]);
|
|
//printf("RT.(%s %f) ",contracts[i],RTprices[i]);
|
|
}
|
|
return(dp->ecbdatenum);
|
|
}
|
|
|
|
int32_t PAX_emitprices(uint32_t pvals[32],struct PAX_data *dp)
|
|
{
|
|
double matrix[MAX_CURRENCIES][MAX_CURRENCIES],RTmatrix[MAX_CURRENCIES][MAX_CURRENCIES],cprices[64],basevals[64]; struct price_resolution prices[256]; int32_t i,nonz = 0;
|
|
memset(cprices,0,sizeof(cprices));
|
|
if ( PAX_getmatrix(basevals,dp,matrix,cprices+1,PAX_bases+1,sizeof(PAX_bases)/sizeof(*PAX_bases)-1) > 0 )
|
|
{
|
|
cprices[0] = dp->KMDBTC;
|
|
/*for (i=0; i<32; i++)
|
|
dp->RTmatrix[i][i] = basevals[i];
|
|
for (i=0; i<32; i++)
|
|
printf("%.6f ",basevals[i]);
|
|
printf("basevals\n");
|
|
for (i=0; i<64; i++)
|
|
printf("%.6f ",cprices[i]);
|
|
printf("cprices\n");*/
|
|
memset(prices,0,sizeof(prices));
|
|
memset(matrix,0,sizeof(matrix));
|
|
memset(RTmatrix,0,sizeof(RTmatrix));
|
|
//peggy_prices(prices,dp->BTCUSD,dp->KMDBTC,PAX_bases,sizeof(PAX_bases)/sizeof(*PAX_bases),cprices,basevals);
|
|
for (i=0; i<sizeof(PAX_bases)/sizeof(*PAX_bases); i++)
|
|
{
|
|
pvals[i] = 0;
|
|
if ( (prices[i].Pval= basevals[i]*1000000000) != 0 )
|
|
{
|
|
nonz++;
|
|
if ( prices[i].Pval > 0xffffffff )
|
|
printf("Pval[%d] overflow error %lld\n",i,(long long)prices[i].Pval);
|
|
else pvals[i] = (uint32_t)prices[i].Pval;
|
|
}
|
|
if ( Debuglevel > 2 )
|
|
printf("{%s %.6f %u}.%d ",PAX_bases[i],Pval(&prices[i]),(uint32_t)prices[i].Pval,peggy_mils(i));
|
|
}
|
|
} else printf("pricematrix returned null\n");
|
|
//printf("nonz.%d\n",nonz);
|
|
return(nonz);
|
|
}
|
|
|
|
double PAX_baseprice(struct PAX_spline splines[],uint32_t timestamp,int32_t basenum)
|
|
{
|
|
double btc,kmd,kmdusd,usdval;
|
|
btc = 1000. * _pairaved(PAX_splineval(&splines[MAX_CURRENCIES+0],timestamp,0),PAX_splineval(&splines[MAX_CURRENCIES+1],timestamp,0));
|
|
kmd = .01 * PAX_splineval(&splines[MAX_CURRENCIES+2],timestamp,0);
|
|
if ( btc != 0. && kmd != 0. )
|
|
{
|
|
kmdusd = (btc * kmd);
|
|
usdval = PAX_splineval(&splines[USD],timestamp,0);
|
|
if ( basenum == USD )
|
|
return(1. / kmdusd);
|
|
else return(PAX_splineval(&splines[basenum],timestamp,0) / (kmdusd * usdval));
|
|
}
|
|
return(0.);
|
|
}
|
|
|
|
double PAX_getprice(char *retbuf,char *base,char *rel,char *contract,struct PAX_data *dp)
|
|
{
|
|
int32_t i,c,basenum,relnum,n = 0; double yprice,daily,revdaily,price;
|
|
price = yprice = daily = revdaily = 0.;
|
|
PAX_ispair(base,rel,contract);
|
|
if ( base[0] != 0 && rel[0] != 0 )
|
|
{
|
|
basenum = PAX_basenum(base), relnum = PAX_basenum(rel);
|
|
if ( basenum >= 0 && relnum >= 0 && basenum < MAX_CURRENCIES && relnum < MAX_CURRENCIES )
|
|
daily = dp->dailyprices[basenum*MAX_CURRENCIES + relnum], revdaily = dp->dailyprices[relnum*MAX_CURRENCIES + basenum];
|
|
}
|
|
for (i=0; i<sizeof(Yahoo_metals)/sizeof(*Yahoo_metals); i++)
|
|
if ( strncmp(Yahoo_metals[i],contract,3) == 0 && strcmp(contract+3,"USD") == 0 )
|
|
{
|
|
yprice = dp->metals[i];
|
|
break;
|
|
}
|
|
sprintf(retbuf,"{\"result\":\"success\",\"contract\":\"%s\",\"base\":\"%s\",\"rel\":\"%s\"",contract,base,rel);
|
|
if ( (c= PAX_contractnum(contract,0)) >= 0 )
|
|
{
|
|
if ( dp->tbids[c] != 0. && dp->tasks[c] != 0. )
|
|
{
|
|
price += (dp->tbids[c] + dp->tasks[c]), n += 2;
|
|
sprintf(retbuf+strlen(retbuf),",\"truefx\":{\"timestamp\":\"%u\",\"bid\":%.8f,\"ask\":%.8f}",dp->ttimestamps[c],dp->tbids[c],dp->tasks[c]);
|
|
}
|
|
if ( dp->fbids[c] != 0. && dp->fasks[c] != 0. )
|
|
{
|
|
price += (dp->fbids[c] + dp->fasks[c]), n += 2;
|
|
sprintf(retbuf+strlen(retbuf),",\"fxcm\":{\"bid\":%.8f,\"ask\":%.8f}",dp->fbids[c],dp->fasks[c]);
|
|
}
|
|
/*if ( dp->ibids[c] != 0. && dp->iasks[c] != 0. )
|
|
{
|
|
price += (dp->ibids[c] + dp->iasks[c]), n += 2;
|
|
sprintf(retbuf+strlen(retbuf),",\"instaforex\":{\"timestamp\":%u,\"bid\":%.8f,\"ask\":%.8f}",dp->itimestamps[c],dp->ibids[c],dp->iasks[c]);
|
|
}*/
|
|
if ( yprice != 0. )
|
|
sprintf(retbuf+strlen(retbuf),",\"yahoo\":{\"price\":%.8f}",yprice);
|
|
if ( daily != 0. || revdaily != 0. )
|
|
sprintf(retbuf+strlen(retbuf),",\"ecb\":{\"date\":\"%s\",\"daily\":%.8f,\"reverse\":%.8f}",dp->edate,daily,revdaily);
|
|
}
|
|
if ( n > 0 )
|
|
price /= n;
|
|
sprintf(retbuf+strlen(retbuf),",\"aveprice\":%.8f,\"n\":%d}",price,n);
|
|
return(price);
|
|
}
|
|
|
|
/*double PAX_aveprice(struct supernet_info *myinfo,char *base)
|
|
{
|
|
struct peggy_info *PEGS; int32_t basenum;
|
|
if ( (PEGS= myinfo->PEGS) != 0 && (basenum= PAX_basenum(base)) >= 0 )
|
|
{
|
|
return(PEGS->data.RTmatrix[basenum][basenum]);
|
|
}
|
|
return(0.);
|
|
}*/
|
|
cJSON *url_json(char *url)
|
|
{
|
|
char *jsonstr; cJSON *json = 0;
|
|
if ( (jsonstr= issue_curl(url)) != 0 )
|
|
{
|
|
//printf("(%s) -> (%s)\n",url,jsonstr);
|
|
json = cJSON_Parse(jsonstr);
|
|
free(jsonstr);
|
|
}
|
|
return(json);
|
|
}
|
|
|
|
cJSON *url_json2(char *url)
|
|
{
|
|
char *jsonstr; cJSON *json = 0;
|
|
if ( (jsonstr= issue_curl(url)) != 0 )
|
|
{
|
|
//printf("(%s) -> (%s)\n",url,jsonstr);
|
|
json = cJSON_Parse(jsonstr);
|
|
free(jsonstr);
|
|
}
|
|
return(json);
|
|
}
|
|
|
|
double PAX_yahoo(char *metal)
|
|
{
|
|
// http://finance.yahoo.com/webservice/v1/symbols/allcurrencies/quote?format=json
|
|
// http://finance.yahoo.com/webservice/v1/symbols/EUR=USD/quote?format=json
|
|
// http://finance.yahoo.com/webservice/v1/symbols/XAU=X/quote?format=json
|
|
// http://finance.yahoo.com/webservice/v1/symbols/XAG=X/quote?format=json
|
|
// http://finance.yahoo.com/webservice/v1/symbols/XPT=X/quote?format=json
|
|
// http://finance.yahoo.com/webservice/v1/symbols/XPD=X/quote?format=json
|
|
char url[1024],*jsonstr; cJSON *json,*obj,*robj,*item,*field; double price = 0.;
|
|
sprintf(url,"http://finance.yahoo.com/webservice/v1/symbols/%s=X/quote?&format=json",metal);
|
|
if ( (jsonstr= issue_curl(url)) != 0 )
|
|
{
|
|
//printf("(%s)\n",jsonstr);
|
|
if ( (json= cJSON_Parse(jsonstr)) != 0 )
|
|
{
|
|
if ( (obj= jobj(json,"list")) != 0 && (robj= jobj(obj,"resources")) != 0 && (item= jitem(robj,0)) != 0 )
|
|
{
|
|
if ( (robj= jobj(item,"resource")) != 0 && (field= jobj(robj,"fields")) != 0 && (price= jdouble(field,"price")) != 0 )
|
|
price = 1. / price;
|
|
}
|
|
free_json(json);
|
|
}
|
|
free(jsonstr);
|
|
}
|
|
if ( Debuglevel > 2 )
|
|
printf("(%s %f) ",metal,price);
|
|
dpow_price("yahoo",metal,price,price);
|
|
return(price);
|
|
}
|
|
|
|
void PAX_btcprices(struct PAX_data *dp,int32_t enddatenum,int32_t numdates)
|
|
{
|
|
int32_t i,n,year,month,day,seconds,datenum; char url[1024],url2[1024],date[64],*dstr,*str;
|
|
uint32_t timestamp,utc32[MAX_SPLINES]; struct tai t;
|
|
cJSON *coindesk,*quandl,*kmdhist,*bpi,*array,*item;
|
|
double kmddaily[MAX_SPLINES],cdaily[MAX_SPLINES],qdaily[MAX_SPLINES],ask,high,low,bid,close,vol,quotevol,open,price = 0.;
|
|
coindesk = url_json("http://api.coindesk.com/v1/bpi/historical/close.json");
|
|
sprintf(url,"https://poloniex.com/public?command=returnChartData¤cyPair=BTC_KMD&start=%ld&end=9999999999&period=86400",(long)(time(NULL)-numdates*3600*24));
|
|
sprintf(url2,"https://poloniex.com/public?command=returnChartData¤cyPair=BTC_BTCD&start=%ld&end=9999999999&period=86400",(long)(time(NULL)-numdates*3600*24));
|
|
if ( (bpi= jobj(coindesk,"bpi")) != 0 )
|
|
{
|
|
datenum = enddatenum;
|
|
memset(utc32,0,sizeof(utc32));
|
|
memset(cdaily,0,sizeof(cdaily));
|
|
if ( datenum == 0 )
|
|
{
|
|
datenum = OS_conv_unixtime(&t,&seconds,(uint32_t)time(NULL));
|
|
printf("got datenum.%d %d %d %d\n",datenum,seconds/3600,(seconds/60)%24,seconds%60);
|
|
}
|
|
for (i=0; i<numdates; i++)
|
|
{
|
|
expand_datenum(date,datenum);
|
|
if ( (price= jdouble(bpi,date)) != 0 )
|
|
{
|
|
utc32[numdates - 1 - i] = OS_conv_datenum(datenum,12,0,0);
|
|
cdaily[numdates - 1 - i] = price * .001;
|
|
if ( i == 0 )
|
|
dpow_price("bpi","BTCUSD",price,price);
|
|
//printf("(%s %u %f) ",date,utc32[numdates - 1 - i],price);
|
|
}
|
|
datenum = ecb_decrdate(&year,&month,&day,date,datenum);
|
|
}
|
|
PAX_genspline(&dp->splines[MAX_CURRENCIES],MAX_CURRENCIES,"coindesk",utc32,cdaily,numdates,cdaily);
|
|
|
|
} else printf("no bpi\n");
|
|
quandl = url_json("https://www.quandl.com/api/v1/datasets/BAVERAGE/USD.json?rows=64");
|
|
if ( 0 && (str= jstr(quandl,"updated_at")) != 0 && (datenum= conv_date(&seconds,str)) > 0 && (array= jarray(&n,quandl,"data")) != 0 )
|
|
{
|
|
printf("datenum.%d data.%d %d\n",datenum,n,cJSON_GetArraySize(array));
|
|
memset(utc32,0,sizeof(utc32)), memset(qdaily,0,sizeof(qdaily));
|
|
for (i=0; i<n&&i<MAX_SPLINES; i++)
|
|
{
|
|
// ["Date","24h Average","Ask","Bid","Last","Total Volume"]
|
|
// ["2015-07-25",289.27,288.84,288.68,288.87,44978.61]
|
|
item = jitem(array,i);
|
|
if ( Debuglevel > 2 )
|
|
printf("(%s) ",cJSON_Print(item));
|
|
if ( (dstr= jstr(jitem(item,0),0)) != 0 && (datenum= conv_date(&seconds,dstr)) > 0 )
|
|
{
|
|
price = jdouble(jitem(item,1),0), ask = jdouble(jitem(item,2),0), bid = jdouble(jitem(item,3),0);
|
|
close = jdouble(jitem(item,4),0), vol = jdouble(jitem(item,5),0);
|
|
if ( Debuglevel > 2 )
|
|
fprintf(stderr,"%d.[%d %f %f %f %f %f].%d ",i,datenum,price,ask,bid,close,vol,n);
|
|
utc32[numdates - 1 - i] = OS_conv_datenum(datenum,12,0,0), qdaily[numdates - 1 - i] = price * .001;
|
|
if ( i == n-1 )
|
|
dpow_price("quandl","BTCUSD",bid,ask);
|
|
}
|
|
}
|
|
PAX_genspline(&dp->splines[MAX_CURRENCIES+1],MAX_CURRENCIES+1,"quandl",utc32,qdaily,n<MAX_SPLINES?n:MAX_SPLINES,qdaily);
|
|
}
|
|
kmdhist = url_json(url);
|
|
//{"date":1406160000,"high":0.01,"low":0.00125,"open":0.01,"close":0.001375,"volume":1.50179994,"quoteVolume":903.58818412,"weightedAverage":0.00166204},
|
|
if ( (array= jarray(&n,kmdhist,0)) != 0 )
|
|
{
|
|
memset(utc32,0,sizeof(utc32)), memset(kmddaily,0,sizeof(kmddaily));
|
|
for (i=0; i<MAX_SPLINES; i++)
|
|
kmddaily[i] = 0.0001 * 100.;
|
|
//printf("GOT.(%s)\n",cJSON_Print(array));
|
|
for (i=0; i<n; i++)
|
|
{
|
|
item = jitem(array,i);
|
|
timestamp = juint(item,"date"), high = jdouble(item,"high"), low = jdouble(item,"low"), open = jdouble(item,"open");
|
|
close = jdouble(item,"close"), vol = jdouble(item,"volume"), quotevol = jdouble(item,"quoteVolume"), price = jdouble(item,"weightedAverage");
|
|
//printf("[%u %f %f %f %f %f %f %f]",timestamp,high,low,open,close,vol,quotevol,price);
|
|
if ( Debuglevel > 2 )
|
|
printf("[%u %d %f]",timestamp,OS_conv_unixtime(&t,&seconds,timestamp),price);
|
|
utc32[i] = timestamp - 12*3600, kmddaily[i] = price * 100.;
|
|
}
|
|
if ( Debuglevel > 2 )
|
|
printf("poloniex.%d\n",n);
|
|
PAX_genspline(&dp->splines[MAX_CURRENCIES+2],MAX_CURRENCIES+2,"kmdhist",utc32,kmddaily,n<MAX_SPLINES?n:MAX_SPLINES,kmddaily);
|
|
}
|
|
// https://poloniex.com/public?command=returnChartData¤cyPair=BTC_KMD&start=1405699200&end=9999999999&period=86400
|
|
}
|
|
|
|
int32_t PAX_ecbparse(char *date,double *prices,char *url,int32_t basenum)
|
|
{
|
|
char *jsonstr,*relstr,*basestr,name[16]; int32_t count=0,i,relnum; cJSON *json,*ratesobj,*item; struct destbuf tmp;
|
|
if ( (jsonstr= issue_curl(url)) != 0 )
|
|
{
|
|
if ( Debuglevel > 2 )
|
|
printf("(%s)\n",jsonstr);
|
|
if ( (json= cJSON_Parse(jsonstr)) != 0 )
|
|
{
|
|
if ( jobj(json,"error") != 0 || jobj(json,"date") == 0 )
|
|
{
|
|
printf("Got error from fixer.io (%s)\n",jsonstr);
|
|
sleep(10);
|
|
}
|
|
else
|
|
{
|
|
copy_cJSON(&tmp,jobj(json,"date")), safecopy(date,tmp.buf,64);
|
|
if ( (basestr= jstr(json,"base")) != 0 && strcmp(basestr,CURRENCIES[basenum]) == 0 && (ratesobj= jobj(json,"rates")) != 0 && (item= ratesobj->child) != 0 )
|
|
{
|
|
while ( item != 0 )
|
|
{
|
|
if ( (relstr= get_cJSON_fieldname(item)) != 0 && (relnum= PAX_basenum(relstr)) >= 0 )
|
|
{
|
|
i = basenum*MAX_CURRENCIES + relnum;
|
|
prices[i] = item->valuedouble;
|
|
//if ( basenum == JPYNUM )
|
|
// prices[i] *= 100.;
|
|
// else if ( relnum == JPYNUM )
|
|
// prices[i] /= 100.;
|
|
count++;
|
|
if ( Debuglevel > 2 )
|
|
printf("(%02d:%02d %f) ",basenum,relnum,prices[i]);
|
|
sprintf(name,"%s%s",CURRENCIES[basenum],CURRENCIES[relnum]);
|
|
} else printf("cant find.(%s)\n",relstr);//, getchar();
|
|
item = item->next;
|
|
}
|
|
}
|
|
}
|
|
free_json(json);
|
|
}
|
|
free(jsonstr);
|
|
}
|
|
return(count);
|
|
}
|
|
|
|
int32_t PAX_ecbprices(char *date,double *prices,int32_t year,int32_t month,int32_t day)
|
|
{
|
|
// http://api.fixer.io/latest?base=CNH
|
|
// http://api.fixer.io/2000-01-03?base=USD
|
|
// "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD"
|
|
char baseurl[512],tmpdate[64],url[512],checkdate[16]; int32_t basenum,count,i,iter,nonz;
|
|
checkdate[0] = 0;
|
|
if ( year == 0 )
|
|
strcpy(baseurl,"http://api.fixer.io/latest?base=");
|
|
else
|
|
{
|
|
sprintf(checkdate,"%d-%02d-%02d",year,month,day);
|
|
sprintf(baseurl,"http://api.fixer.io/%s?base=",checkdate);
|
|
}
|
|
count = 0;
|
|
for (iter=0; iter<2; iter++)
|
|
{
|
|
for (basenum=0; basenum<sizeof(CURRENCIES)/sizeof(*CURRENCIES); basenum++)
|
|
{
|
|
if ( strcmp(CURRENCIES[basenum],"XAU") == 0 || basenum >= MAX_CURRENCIES )
|
|
break;
|
|
if ( iter == 0 )
|
|
{
|
|
sprintf(url,"%s%s",baseurl,CURRENCIES[basenum]);
|
|
count += PAX_ecbparse(basenum == 0 ? date : tmpdate,prices,url,basenum);
|
|
usleep(100000);
|
|
if ( (basenum != 0 && strcmp(tmpdate,date) != 0) || (checkdate[0] != 0 && strcmp(checkdate,date) != 0) )
|
|
{
|
|
//printf("date mismatch (%s) != (%s) or checkdate.(%s)\n",tmpdate,date,checkdate);
|
|
return(-1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (nonz=i=0; i<sizeof(CURRENCIES)/sizeof(*CURRENCIES); i++)
|
|
{
|
|
if ( strcmp(CURRENCIES[i],"XAU") == 0 || i >= MAX_CURRENCIES )
|
|
break;
|
|
if ( prices[MAX_CURRENCIES*basenum + i] != 0. )
|
|
nonz++;
|
|
if ( Debuglevel > 2 )
|
|
printf("%8.5f ",prices[MAX_CURRENCIES*basenum + i]);
|
|
}
|
|
if ( Debuglevel > 2 )
|
|
printf("%s.%d %d\n",CURRENCIES[basenum],basenum,nonz);
|
|
}
|
|
}
|
|
}
|
|
return(count);
|
|
}
|
|
|
|
int32_t ecb_matrix(double basevals[MAX_CURRENCIES],double matrix[MAX_CURRENCIES][MAX_CURRENCIES],char *date)
|
|
{
|
|
FILE *fp=0; double price,bid,ask; int32_t n=0,datenum,relid,baseid,year=0,seconds,month=0,day=0,loaded = 0; char name[16],fname[64],_date[64];
|
|
if ( date == 0 )
|
|
date = _date, memset(_date,0,sizeof(_date));
|
|
//printf("ecb_matrix(%s)\n",date);
|
|
sprintf(fname,"%s/ECB/%s",GLOBAL_DBDIR,date), OS_compatible_path(fname);
|
|
if ( date[0] != 0 && (fp= fopen(fname,"rb")) != 0 )
|
|
{
|
|
if ( fread(matrix,1,sizeof(matrix[0][0])*MAX_CURRENCIES*MAX_CURRENCIES,fp) == sizeof(matrix[0][0])*MAX_CURRENCIES*MAX_CURRENCIES )
|
|
loaded = 1;
|
|
else printf("fread error\n");
|
|
fclose(fp);
|
|
} else printf("ecb_matrix.(%s) load error fp.%p\n",fname,fp);
|
|
datenum = conv_date(&seconds,date);
|
|
year = datenum / 10000, month = (datenum / 100) % 100, day = (datenum % 100);
|
|
if ( loaded == 0 )
|
|
{
|
|
if ( (n= PAX_ecbprices(date,&matrix[0][0],year,month,day)) > 0 )
|
|
{
|
|
sprintf(fname,"%s/ECB/%s",GLOBAL_DBDIR,date), OS_compatible_path(fname);
|
|
if ( (fp= fopen(fname,"wb")) != 0 )
|
|
{
|
|
if ( fwrite(matrix,1,sizeof(matrix[0][0])*MAX_CURRENCIES*MAX_CURRENCIES,fp) == sizeof(matrix[0][0])*MAX_CURRENCIES*MAX_CURRENCIES )
|
|
loaded = 1;
|
|
fclose(fp);
|
|
}
|
|
} //else printf("peggy_matrix error loading %d.%d.%d\n",year,month,day);
|
|
}
|
|
else
|
|
{
|
|
PAX_calcmatrix(matrix);
|
|
for (baseid=0; baseid<MAX_CURRENCIES-1; baseid++)
|
|
for (relid=baseid+1; relid<MAX_CURRENCIES; relid++)
|
|
{
|
|
bid = ask = 0.;
|
|
sprintf(name,"%s%s",CURRENCIES[baseid],CURRENCIES[relid]);
|
|
if ( (price= matrix[relid][baseid]) > SMALLVAL )
|
|
price = 1. / price;
|
|
if ( matrix[baseid][relid] > SMALLVAL && matrix[baseid][relid] < price )
|
|
bid = matrix[baseid][relid], ask = price;
|
|
else bid = price, ask = matrix[baseid][relid];
|
|
if ( bid > SMALLVAL && ask > SMALLVAL )
|
|
{
|
|
dpow_price("ecb",name,bid,ask);
|
|
n++;
|
|
}
|
|
}
|
|
for (baseid=0; baseid<MAX_CURRENCIES; baseid++)
|
|
basevals[baseid] = matrix[baseid][baseid];
|
|
}
|
|
if ( loaded == 0 && n == 0 )
|
|
{
|
|
printf("peggy_matrix couldnt process loaded.%d n.%d\n",loaded,n);
|
|
return(-1);
|
|
}
|
|
//"2000-01-03"
|
|
if ( (datenum= conv_date(&seconds,date)) < 0 )
|
|
return(-1);
|
|
//printf("loaded.(%s) nonz.%d (%d %d %d) datenum.%d\n",date,n,year,month,day,datenum);
|
|
return(datenum);
|
|
}
|
|
|
|
void PAX_update(struct PAX_data *dp,double *btcusdp,double *kmdbtcp)
|
|
{
|
|
int32_t i,n,iter,seconds,datenum; uint32_t timestamp; char url[1024],url2[1024],*dstr,*str;
|
|
double kmddaily=0.,btcusd=0.,ask,high,low,bid,close,vol,quotevol,open,price = 0.;
|
|
//cJSON *kmdtrades,*kmdtrades2,*,*bitcoincharts,;
|
|
cJSON *quandl,*kmdhist,*array,*item,*bitcoinave,*blockchaininfo,*btctrades,*coindesk=0;
|
|
sprintf(url,"https://poloniex.com/public?command=returnTradeHistory¤cyPair=USDT_BTC&start=%u&end=%u",(uint32_t)time(NULL)-60,(uint32_t)time(NULL));
|
|
btctrades = url_json(url);
|
|
//kmdtrades = url_json("https://poloniex.com/public?command=returnTradeHistory¤cyPair=USDT_BTC");
|
|
//kmdtrades2 = url_json("https://bittrex.com/api/v1.1/public/getmarkethistory?market=BTC-KMD&count=50");
|
|
*kmdbtcp = 0;
|
|
bitcoinave = 0;//url_json("https://api.bitcoinaverage.com/ticker/USD/");
|
|
//bitcoincharts = url_json("http://api.bitcoincharts.com/v1/weighted_prices.json");
|
|
blockchaininfo = url_json("https://blockchain.info/ticker");
|
|
coindesk = 0;//url_json("http://api.coindesk.com/v1/bpi/historical/close.json");
|
|
sprintf(url,"https://poloniex.com/public?command=returnChartData¤cyPair=BTC_KMD&start=%ld&end=9999999999&period=86400",(long)(time(NULL)-3600*24));
|
|
sprintf(url2,"https://poloniex.com/public?command=returnChartData¤cyPair=BTC_BTCD&start=%ld&end=9999999999&period=86400",(long)(time(NULL)-3600*24));
|
|
quandl = 0;//url_json("https://www.quandl.com/api/v1/datasets/BAVERAGE/USD.json?rows=1");
|
|
if ( 0 && (str= jstr(quandl,"updated_at")) != 0 && (datenum= conv_date(&seconds,str)) > 0 && (array= jarray(&n,quandl,"data")) != 0 )
|
|
{
|
|
//printf("datenum.%d data.%d %d\n",datenum,n,cJSON_GetArraySize(array));
|
|
for (i=0; i<1; i++)
|
|
{
|
|
// ["Date","24h Average","Ask","Bid","Last","Total Volume"]
|
|
// ["2015-07-25",289.27,288.84,288.68,288.87,44978.61]
|
|
item = jitem(array,i);
|
|
if ( (dstr= jstr(jitem(item,0),0)) != 0 && (datenum= conv_date(&seconds,dstr)) > 0 )
|
|
{
|
|
btcusd = price = jdouble(jitem(item,1),0), ask = jdouble(jitem(item,2),0), bid = jdouble(jitem(item,3),0);
|
|
close = jdouble(jitem(item,4),0), vol = jdouble(jitem(item,5),0);
|
|
//fprintf(stderr,"%d.[%d %f %f %f %f %f].%d ",i,datenum,price,ask,bid,close,vol,n);
|
|
}
|
|
}
|
|
}
|
|
if ( 1 )
|
|
{
|
|
double USD_average,avebid,aveask,bidvol,askvol,highbid,lowask,CMC_average,changes[3]; //struct exchange_quote sortbuf[512]; struct supernet_info *myinfo = SuperNET_MYINFO(0); cJSON *argjson = cJSON_Parse("{}");
|
|
//aveask = instantdex_aveprice(myinfo,sortbuf,(int32_t)(sizeof(sortbuf)/sizeof(*sortbuf)),&askvol,"KMD","BTC",1,argjson);
|
|
//avebid = instantdex_aveprice(myinfo,sortbuf,(int32_t)(sizeof(sortbuf)/sizeof(*sortbuf)),&bidvol,"KMD","BTC",-1,argjson);
|
|
if ( 0 && avebid > SMALLVAL && aveask > SMALLVAL )
|
|
{
|
|
price = (avebid*bidvol + aveask*askvol) / (bidvol + askvol);
|
|
*kmdbtcp = price;
|
|
printf("set KMD price %f\n",price);
|
|
dp->KMDBTC = price;
|
|
}
|
|
else if ( (dp->KMDBTC= get_theoretical(&avebid,&aveask,&highbid,&lowask,&CMC_average,changes,"komodo","KMD","BTC",&USD_average)) > SMALLVAL )
|
|
*kmdbtcp = dp->KMDBTC;
|
|
else
|
|
{
|
|
for (iter=1; iter<2; iter++)
|
|
{
|
|
kmdhist = url_json(iter == 0 ? url : url2);
|
|
//{"date":1406160000,"high":0.01,"low":0.00125,"open":0.01,"close":0.001375,"volume":1.50179994,"quoteVolume":903.58818412,"weightedAverage":0.00166204},
|
|
if ( kmdhist != 0 && (array= jarray(&n,kmdhist,0)) != 0 )
|
|
{
|
|
//printf("GOT.(%s)\n",cJSON_Print(array));
|
|
for (i=0; i<1; i++)
|
|
{
|
|
item = jitem(array,i);
|
|
timestamp = juint(item,"date"), high = jdouble(item,"high"), low = jdouble(item,"low"), open = jdouble(item,"open");
|
|
close = jdouble(item,"close"), vol = jdouble(item,"volume"), quotevol = jdouble(item,"quoteVolume"), price = jdouble(item,"weightedAverage");
|
|
//printf("[%u %f %f %f %f %f %f %f]",timestamp,high,low,open,close,vol,quotevol,price);
|
|
//printf("[%u %d %f]",timestamp,OS_conv_unixtime(&seconds,timestamp),price);
|
|
if ( price != 0 )
|
|
{
|
|
if ( iter == 0 )
|
|
dp->KMDBTC = *kmdbtcp = kmddaily;
|
|
else dp->BTCDBTC = price;
|
|
}
|
|
}
|
|
//printf("poloniex.%d\n",n);
|
|
}
|
|
if ( kmdhist != 0 )
|
|
free_json(kmdhist);
|
|
}
|
|
}
|
|
}
|
|
if ( (*kmdbtcp= dp->KMDBTC) == 0. )
|
|
*kmdbtcp = dp->BTCDBTC / 50.22;
|
|
if ( (rand() % 100) == 0 )
|
|
printf("KMD/BTC %.8f\n",*kmdbtcp);
|
|
if ( btctrades != 0 && (array= jarray(&n,btctrades,0)) != 0 )
|
|
{
|
|
//printf("GOT.(%s)\n",cJSON_Print(array));
|
|
for (i=0; i<1; i++)
|
|
{
|
|
item = jitem(array,i);
|
|
timestamp = juint(item,"date");
|
|
//printf("[%u %f %f %f %f %f %f %f]",timestamp,high,low,open,close,vol,quotevol,price);
|
|
//printf("[%u %d %f]",timestamp,OS_conv_unixtime(&seconds,timestamp),price);
|
|
*btcusdp = jdouble(item,"rate");
|
|
//printf("(%s) -> %f\n",jprint(item,0),btcusd);
|
|
}
|
|
free(btctrades);
|
|
//printf("poloniex.%d\n",n);
|
|
}
|
|
if ( 0 && bitcoinave != 0 )
|
|
{
|
|
if ( (price= jdouble(bitcoinave,"24h_avg")) > SMALLVAL )
|
|
{
|
|
//printf("bitcoinave %f %f\n",btcusd,price);
|
|
dpow_price("bitcoinave","BTCUSD",price,price);
|
|
dxblend(&btcusd,price,0.5);
|
|
}
|
|
free_json(bitcoinave);
|
|
}
|
|
if ( quandl != 0 )
|
|
free_json(quandl);
|
|
if ( coindesk != 0 )
|
|
free_json(coindesk);
|
|
if ( blockchaininfo != 0 )
|
|
{
|
|
if ( (item= jobj(blockchaininfo,"USD")) != 0 && item != 0 && (price= jdouble(item,"15m")) > SMALLVAL )
|
|
{
|
|
dpow_price("blockchain.info","BTCUSD",price,price);
|
|
printf("blockchaininfo %f %f\n",btcusd,price);
|
|
dxblend(&btcusd,price,0.5);
|
|
}
|
|
free_json(blockchaininfo);
|
|
}
|
|
}
|
|
|
|
double blend_price(double *volp,double wtA,cJSON *jsonA,double wtB,cJSON *jsonB)
|
|
{
|
|
//A.{"ticker":{"base":"BTS","target":"CNY","price":"0.02958291","volume":"3128008.39295500","change":"0.00019513","markets":[{"market":"BTC38","price":"0.02960000","volume":3051650.682955},{"market":"Bter","price":"0.02890000","volume":76357.71}]},"timestamp":1438490881,"success":true,"error":""}
|
|
// B.{"id":"bts\/cny","price":"0.02940000","price_before_24h":"0.02990000","volume_first":"3048457.6857147217","volume_second":"90629.45859575272","volume_btc":"52.74","best_market":"btc38","latest_trade":"2015-08-02 03:57:38","coin1":"BitShares","coin2":"CNY","markets":[{"market":"btc38","price":"0.02940000","volume":"3048457.6857147217","volume_btc":"52.738317962865"},{"market":"bter","price":"0.04350000","volume":"0","volume_btc":"0"}]}
|
|
double priceA,priceB,priceB24,price,volA,volB; cJSON *obj;
|
|
priceA = priceB = priceB24= price = volA = volB = 0.;
|
|
if ( jsonA != 0 && (obj= jobj(jsonA,"ticker")) != 0 )
|
|
{
|
|
priceA = jdouble(obj,"price");
|
|
volA = jdouble(obj,"volume");
|
|
}
|
|
if ( jsonB != 0 )
|
|
{
|
|
priceB = jdouble(jsonB,"price");
|
|
priceB24 = jdouble(jsonB,"price_before_24h");
|
|
volB = jdouble(jsonB,"volume_first");
|
|
}
|
|
//printf("priceA %f volA %f, priceB %f %f volB %f\n",priceA,volA,priceB,priceB24,volB);
|
|
if ( priceB > SMALLVAL && priceB24 > SMALLVAL )
|
|
priceB = (priceB * .1) + (priceB24 * .9);
|
|
else if ( priceB < SMALLVAL )
|
|
priceB = priceB24;
|
|
if ( priceA*volA < SMALLVAL )
|
|
price = priceB;
|
|
else if ( priceB*volB < SMALLVAL )
|
|
price = priceA;
|
|
else price = (wtA * priceA) + (wtB * priceB);
|
|
*volp = (volA + volB);
|
|
return(price);
|
|
}
|
|
|
|
void _crypto_update(double cryptovols[2][9][2],struct PAX_data *dp,int32_t selector)
|
|
{
|
|
char *cryptonatorA = "https://www.cryptonator.com/api/full/%s-%s"; //unity-btc
|
|
char *cryptocoinchartsB = "http://api.cryptocoincharts.info/tradingPair/%s_%s"; //bts_btc
|
|
char *cryptostrs[9] = { "btc", "nxt", "unity", "eth", "kmd", "xmr", "bts", "xcp", "etc" };
|
|
int32_t iter,i,j; double btcusd,kmdbtc,cnyusd,prices[9][2],volumes[9][2];
|
|
char base[16],rel[16],url[512],name[16],*str; cJSON *jsonA,*jsonB;
|
|
cnyusd = dp->CNYUSD;
|
|
btcusd = dp->BTCUSD;
|
|
if ( (kmdbtc= dp->KMDBTC) == 0. )
|
|
;//kmdbtc = dp->BTCDBTC / 50.22;
|
|
printf("DEPRECATED: update with btcusd %f kmd %f cnyusd %f cnybtc %f\n",btcusd,kmdbtc,cnyusd,cnyusd/btcusd);
|
|
return;
|
|
if ( btcusd < SMALLVAL || kmdbtc < SMALLVAL )
|
|
{
|
|
PAX_update(dp,&btcusd,&kmdbtc);
|
|
//printf("PAX_update with btcusd %f kmd %f\n",btcusd,kmdbtc);
|
|
}
|
|
memset(prices,0,sizeof(prices));
|
|
memset(volumes,0,sizeof(volumes));
|
|
for (j=0; j<sizeof(cryptostrs)/sizeof(*cryptostrs); j++)
|
|
{
|
|
str = cryptostrs[j];
|
|
/*if ( strcmp(str,"etc") == 0 )
|
|
{
|
|
if ( prices[3][0] > SMALLVAL )
|
|
break;
|
|
i = 3;
|
|
} else*/
|
|
i = j;
|
|
for (iter=0; iter<1; iter++)
|
|
{
|
|
if ( i == 0 && iter == 0 )
|
|
strcpy(base,"kmd"), strcpy(rel,"btc");
|
|
else strcpy(base,str), strcpy(rel,iter==0?"btc":"cny");
|
|
sprintf(name,"%s%s",base,rel);
|
|
//if ( selector == 0 )
|
|
{
|
|
sprintf(url,cryptonatorA,base,rel);
|
|
jsonA = url_json(url);
|
|
}
|
|
//else
|
|
{
|
|
sprintf(url,cryptocoinchartsB,base,rel);
|
|
jsonB = url_json(url);
|
|
}
|
|
prices[i][iter] = blend_price(&volumes[i][iter],0.4,jsonA,0.6,jsonB);
|
|
if ( iter == 1 )
|
|
{
|
|
if ( btcusd > SMALLVAL )
|
|
{
|
|
prices[i][iter] *= cnyusd / btcusd;
|
|
volumes[i][iter] *= cnyusd / btcusd;
|
|
} else prices[i][iter] = volumes[i][iter] = 0.;
|
|
}
|
|
cryptovols[0][i][iter] = _pairaved(cryptovols[0][i][iter],prices[i][iter]);
|
|
//cryptovols[1][i][iter] = _pairaved(cryptovols[1][i][iter],volumes[i][iter]);
|
|
dpow_price("cryptonator",name,prices[i][iter],prices[i][iter]);
|
|
if ( Debuglevel > 2 )
|
|
printf("(%f %f).%d:%d ",cryptovols[0][i][iter],cryptovols[1][i][iter],i,iter);
|
|
//if ( cnyusd < SMALLVAL || btcusd < SMALLVAL )
|
|
// break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void PAX_RTupdate(double cryptovols[2][9][2],double RTmetals[4],double *RTprices,struct PAX_data *dp)
|
|
{
|
|
char *cryptostrs[9] = { "btc", "nxt", "unity", "eth", "etc", "kmd", "xmr", "bts", "xcp" };
|
|
int32_t iter,i,c,baserel,basenum,relnum; double cnyusd,btcusd,kmdbtc,bid=0.,ask=0.,price,vol,prices[8][2],volumes[8][2];
|
|
char base[16],rel[16];
|
|
PAX_update(dp,&btcusd,&kmdbtc);
|
|
memset(prices,0,sizeof(prices));
|
|
memset(volumes,0,sizeof(volumes));
|
|
for (i=0; i<sizeof(cryptostrs)/sizeof(*cryptostrs); i++)
|
|
for (iter=0; iter<2; iter++)
|
|
{
|
|
prices[i][iter] = cryptovols[0][i][iter];
|
|
volumes[i][iter] = cryptovols[1][i][iter];
|
|
}
|
|
if ( prices[0][0] > SMALLVAL )
|
|
dxblend(&kmdbtc,prices[0][0],.9);
|
|
dxblend(&dp->kmdbtc,kmdbtc,.995);
|
|
if ( dp->KMDBTC < SMALLVAL )
|
|
dp->KMDBTC = dp->kmdbtc;
|
|
if ( (cnyusd= dp->CNYUSD) > SMALLVAL )
|
|
{
|
|
if ( prices[0][1] > SMALLVAL )
|
|
{
|
|
//printf("cnyusd %f, btccny %f -> btcusd %f %f\n",cnyusd,prices[0][1],prices[0][1]*cnyusd,btcusd);
|
|
btcusd = prices[0][1] * cnyusd;
|
|
if ( dp->btcusd < SMALLVAL )
|
|
dp->btcusd = btcusd;
|
|
else dxblend(&dp->btcusd,btcusd,.995);
|
|
if ( dp->BTCUSD < SMALLVAL )
|
|
dp->BTCUSD = dp->btcusd;
|
|
printf("cnyusd %f, btccny %f -> btcusd %f %f -> %f %f %f\n",cnyusd,prices[0][1],prices[0][1]*cnyusd,btcusd,dp->btcusd,dp->btcusd,dp->BTCUSD);
|
|
}
|
|
}
|
|
for (i=1; i<sizeof(cryptostrs)/sizeof(*cryptostrs); i++)
|
|
{
|
|
vol = volumes[i][0];
|
|
vol += volumes[i][1];
|
|
if ( vol > SMALLVAL )
|
|
{
|
|
price = ((prices[i][0] * volumes[i][0]) + (prices[i][1] * volumes[i][1])) / vol;
|
|
if ( Debuglevel > 2 )
|
|
printf("%s %f v%f + %f v%f -> %f %f\n",cryptostrs[i],prices[i][0],volumes[i][0],prices[i][1],volumes[i][1],price,dp->cryptos[i]);
|
|
dxblend(&dp->cryptos[i],price,.995);
|
|
}
|
|
}
|
|
btcusd = dp->BTCUSD;
|
|
kmdbtc = dp->KMDBTC;
|
|
if ( Debuglevel > 2 )
|
|
printf(" update with btcusd %f kmd %f\n",btcusd,kmdbtc);
|
|
if ( btcusd < SMALLVAL || kmdbtc < SMALLVAL )
|
|
{
|
|
PAX_update(dp,&btcusd,&kmdbtc);
|
|
if ( Debuglevel > 2 )
|
|
printf(" price777_update with btcusd %f kmd %f\n",btcusd,kmdbtc);
|
|
} else dp->BTCUSD = btcusd, dp->KMDBTC = kmdbtc;
|
|
for (c=0; c<sizeof(CONTRACTS)/sizeof(*CONTRACTS); c++)
|
|
{
|
|
for (iter=0; iter<3; iter++)
|
|
{
|
|
switch ( iter )
|
|
{
|
|
case 0: bid = dp->tbids[c], ask = dp->tasks[c]; break;
|
|
case 1: bid = dp->fbids[c], ask = dp->fasks[c]; break;
|
|
case 2: bid = dp->ibids[c], ask = dp->iasks[c]; break;
|
|
}
|
|
if ( (price= _pairaved(bid,ask)) > SMALLVAL )
|
|
{
|
|
if ( Debuglevel > 2 )
|
|
printf("%.6f ",price);
|
|
dxblend(&RTprices[c],price,.995);
|
|
if ( 0 && (baserel= PAX_ispair(base,rel,CONTRACTS[c])) >= 0 )
|
|
{
|
|
basenum = (baserel >> 8) & 0xff, relnum = baserel & 0xff;
|
|
if ( basenum < 32 && relnum < 32 )
|
|
{
|
|
//printf("%s.%d %f <- %f\n",CONTRACTS[c],c,RTmatrix[basenum][relnum],RTprices[c]);
|
|
//dxblend(&RTmatrix[basenum][relnum],RTprices[c],.999);
|
|
}
|
|
}
|
|
if ( strcmp(CONTRACTS[c],"XAUUSD") == 0 )
|
|
dxblend(&RTmetals[0],price,.995);
|
|
}
|
|
}
|
|
}
|
|
for (i=0; i<sizeof(Yahoo_metals)/sizeof(*Yahoo_metals); i++)
|
|
if ( dp->metals[i] != 0 )
|
|
dxblend(&RTmetals[i],dp->metals[i],.995);
|
|
}
|
|
|
|
void PAX_bidask(struct exchange_info *exchange,uint32_t *timestamps,double *bids,double *asks,int32_t baseid,int32_t relid)
|
|
{
|
|
int32_t contractnum; struct exchange_quote bidasks[2];
|
|
contractnum = Baserel_contractnum[baseid][relid];
|
|
(*exchange->issue.price)(exchange,CURRENCIES[baseid],CURRENCIES[relid],bidasks,1,0.,0,0);
|
|
//bids[contractnum] = bidasks[0].price;
|
|
//asks[contractnum] = bidasks[1].price;
|
|
//timestamps[contractnum] = bidasks[0].timestamp;
|
|
//printf("%s%s.(%s %.6f) %s\n",CURRENCIES[baseid],CURRENCIES[relid],CONTRACTS[contractnum],_pairaved(bids[contractnum],asks[contractnum]),exchange->name);
|
|
}
|
|
|
|
struct exchange_info *PAX_bidasks(char *exchangestr,uint32_t *timestamps,double *bids,double *asks)
|
|
{
|
|
int32_t baseid,relid; struct exchange_info *exchange;
|
|
if ( (exchange= exchanges777_find(exchangestr)) != 0 )
|
|
{
|
|
for (baseid=0; baseid<8; baseid++)
|
|
{
|
|
for (relid=0; relid<8; relid++)
|
|
{
|
|
if ( Currency_contractdirs[baseid][relid] > 0 )
|
|
PAX_bidask(exchange,timestamps,bids,asks,baseid,relid);
|
|
}
|
|
}
|
|
} else printf("cant find (%s) exchange\n",exchangestr);
|
|
return(exchange);
|
|
}
|
|
|
|
void dpow_price(char *exchange,char *name,double bid,double ask)
|
|
{
|
|
// adjust MAX_CURRENCIES, btcusd, btccny
|
|
//printf("%-12s %16.8f %16.8f %s\n",name,bid,ask,exchange);
|
|
}
|
|
|
|
uint32_t PAX_val32(double val)
|
|
{
|
|
uint32_t val32 = 0; struct price_resolution price;
|
|
if ( (price.Pval= val*1000000000) != 0 )
|
|
{
|
|
if ( price.Pval > 0xffffffff )
|
|
printf("Pval overflow error %lld\n",(long long)price.Pval);
|
|
else val32 = (uint32_t)price.Pval;
|
|
}
|
|
return(val32);
|
|
}
|
|
|
|
double PAX_val(uint32_t pval,int32_t baseid)
|
|
{
|
|
if ( baseid >= 0 && baseid < MAX_CURRENCIES )
|
|
return(((double)pval / 1000000000.) / MINDENOMS[baseid]);
|
|
return(0.);
|
|
}
|
|
|
|
void PAX_genecbsplines(struct PAX_data *dp)
|
|
{
|
|
static portable_mutex_t mutex; static int32_t initflag;
|
|
int32_t i,j,datenum,seconds,numsamples; double prices[128][MAX_SPLINES],splineval,diff; uint32_t pvals[MAX_CURRENCIES],utc32[MAX_SPLINES],timestamp; struct tai t;
|
|
if ( initflag == 0 )
|
|
{
|
|
portable_mutex_init(&mutex);
|
|
initflag = 1;
|
|
}
|
|
portable_mutex_lock(&mutex);
|
|
for (i=numsamples=0; i<28; i++)
|
|
{
|
|
datenum = OS_conv_unixtime(&t,&seconds,(uint32_t)time(NULL)-(28-i+1)*24*3600);
|
|
expand_datenum(dp->edate,datenum);
|
|
timestamp = OS_conv_datenum(datenum,12,0,0);
|
|
printf("i.%d datenum.%d %s t%u\n",i,datenum,dp->edate,timestamp);
|
|
if ( (datenum= ecb_matrix(dp->basevals,dp->ecbmatrix,dp->edate)) > 0 )
|
|
{
|
|
utc32[numsamples] = timestamp;
|
|
for (j=0; j<MAX_CURRENCIES; j++)
|
|
{
|
|
pvals[j] = PAX_val32(dp->basevals[j]);
|
|
prices[j][numsamples] = dp->basevals[j];
|
|
}
|
|
numsamples++;
|
|
}
|
|
}
|
|
for (j=0; j<3; j++)
|
|
utc32[numsamples + j] = utc32[numsamples + j - 1] + (24 * 3600);
|
|
for (j=0; j<MAX_CURRENCIES; j++)
|
|
{
|
|
PAX_genspline(&dp->splines[j],j,CURRENCIES[j],utc32,prices[j],numsamples,prices[j]);
|
|
splineval = PAX_splineval(&dp->splines[j],utc32[numsamples-1]- 8*3600,1);
|
|
diff = (prices[j][numsamples-1] - splineval);
|
|
prices[j][numsamples] = prices[j][numsamples-1] + diff;
|
|
diff += prices[j][numsamples-1] - PAX_splineval(&dp->splines[j],utc32[numsamples-1] - 12*3600,1);
|
|
prices[j][numsamples+1] = prices[j][numsamples-1] + diff;
|
|
diff += prices[j][numsamples-1] - PAX_splineval(&dp->splines[j],utc32[numsamples-1] - 16*3600,1);
|
|
prices[j][numsamples+2] = prices[j][numsamples-1] + diff;
|
|
//printf("%s splineval %f vs %f %f %f\n",CURRENCIES[j],prices[j][numsamples-1],prices[j][numsamples],prices[j][numsamples+1],prices[j][numsamples+2]);
|
|
PAX_genspline(&dp->splines[j],j,CURRENCIES[j],utc32,prices[j],numsamples+3,prices[j]);
|
|
}
|
|
portable_mutex_unlock(&mutex);
|
|
}
|
|
|
|
#define BTCFACTOR_TIMESTAMP 1503746319
|
|
#define BTCFACTOR_HEIGHT 466266
|
|
|
|
int32_t PAX_idle(struct supernet_info *myinfo)//struct PAX_data *argdp,int32_t idlegap)
|
|
{
|
|
static double lastupdate,lastdayupdate; static uint32_t didinit; static char *userhome; int32_t idlegap = 10;
|
|
FILE *fp; long filesize; char fname[512]; double splineval; uint32_t pvals[128],timestamp; int32_t i,datenum,seconds,c; struct tai t; struct PAX_data *dp; uint8_t data[512];
|
|
if ( Currencymasks[0] == 0 )
|
|
return(0);
|
|
if ( time(NULL) > didinit+12*3600 )
|
|
{
|
|
if ( (userhome= OS_filestr(&filesize,"userhome.txt")) == 0 )
|
|
userhome = "root";
|
|
else
|
|
{
|
|
while ( (c= userhome[strlen(userhome)-1]) == '\r' || c == '\n' || c == ' ' || c == '\t' )
|
|
{
|
|
userhome[strlen(userhome)-1] = 0;
|
|
}
|
|
}
|
|
if ( myinfo->PAXDATA == 0 )
|
|
myinfo->PAXDATA = calloc(1,sizeof(*dp));
|
|
dp = myinfo->PAXDATA;
|
|
PAX_genecbsplines(dp);
|
|
printf("generated splines\n");
|
|
didinit = (uint32_t)time(NULL);
|
|
datenum = OS_conv_unixtime(&t,&seconds,didinit);
|
|
expand_datenum(dp->edate,datenum);
|
|
}
|
|
dp = myinfo->PAXDATA;
|
|
/*if ( 0 && time(NULL) > dp->lastupdate+10 )
|
|
{
|
|
_crypto_update(dp->cryptovols,dp,1);
|
|
dp->lastupdate = (uint32_t)time(NULL);
|
|
}*/
|
|
if ( OS_milliseconds() > lastupdate + (1000*idlegap) )
|
|
{
|
|
lastupdate = OS_milliseconds();
|
|
if ( OS_milliseconds() > lastdayupdate + 60000*60 )
|
|
{
|
|
lastdayupdate = OS_milliseconds();
|
|
datenum = OS_conv_unixtime(&t,&seconds,(uint32_t)time(NULL));
|
|
expand_datenum(dp->edate,datenum);
|
|
if ( (datenum= ecb_matrix(dp->basevals,dp->ecbmatrix,dp->edate)) > 0 && datenum != dp->ecbdatenum )
|
|
{
|
|
dp->ecbdatenum = datenum;
|
|
dp->ecbyear = dp->ecbdatenum / 10000, dp->ecbmonth = (dp->ecbdatenum / 100) % 100, dp->ecbday = (dp->ecbdatenum % 100);
|
|
expand_datenum(dp->edate,datenum);
|
|
memcpy(dp->RTmatrix,dp->ecbmatrix,sizeof(dp->RTmatrix));
|
|
PAX_genecbsplines(dp);
|
|
}
|
|
}
|
|
if ( 0 )
|
|
{
|
|
for (i=0; i<sizeof(Yahoo_metals)/sizeof(*Yahoo_metals); i++)
|
|
dp->metals[i] = PAX_yahoo(Yahoo_metals[i]);
|
|
PAX_bidasks("truefx",dp->ttimestamps,dp->tbids,dp->tasks);
|
|
PAX_bidasks("fxcm",dp->ftimestamps,dp->fbids,dp->fasks);
|
|
/*if ( (exchange= PAX_bidasks("instaforex",dp->itimestamps,dp->ibids,dp->iasks)) != 0 )
|
|
{
|
|
if ( (contractnum= PAX_contractnum("XAU","USD")) >= 0 )
|
|
{
|
|
(*exchange->issue.price)(exchange,"XAU","USD",bidasks,1,0.,0,0);
|
|
dp->ibids[contractnum] = bidasks[0].price;
|
|
dp->iasks[contractnum] = bidasks[1].price;
|
|
dp->itimestamps[contractnum] = bidasks[0].timestamp;
|
|
}
|
|
}*/
|
|
//printf("BTCUSD %f %f %f\n",btcusd,dp->btcusd,dp->BTCUSD);
|
|
if ( dp->ecbmatrix[USD][USD] > SMALLVAL && dp->ecbmatrix[CNY][CNY] > SMALLVAL )
|
|
dp->CNYUSD = (dp->ecbmatrix[CNY][CNY] / dp->ecbmatrix[USD][USD]);
|
|
PAX_RTupdate(dp->cryptovols,dp->RTmetals,dp->RTprices,dp);
|
|
PAX_emitprices(pvals,dp);
|
|
}
|
|
timestamp = (uint32_t)time(NULL);
|
|
int32_t dispflag = ((rand() % 6) == 0);
|
|
//printf("PAX_IDLE.%d %.8f %.8f\n",dispflag,dp->kmdbtc,dp->btcusd);
|
|
if ( dp->kmdbtc == 0 || dp->btcusd == 0 || dispflag != 0 )
|
|
{
|
|
PAX_update(dp,&dp->btcusd,&dp->kmdbtc);
|
|
for (i=0; i<MAX_CURRENCIES; i++)
|
|
{
|
|
splineval = PAX_splineval(&dp->splines[i],timestamp,0);
|
|
pvals[6+i] = PAX_val32(splineval);
|
|
if ( dispflag != 0 )
|
|
printf("%u ",pvals[6+i]);
|
|
}
|
|
if ( pvals[6+CNY] != 0 && pvals[6+USD] != 0 )
|
|
dp->CNYUSD = ((double)pvals[6 + CNY] / pvals[6 + USD]) * MINDENOMS[USD] / MINDENOMS[CNY];
|
|
pvals[1] = timestamp;
|
|
pvals[2] = MAX_CURRENCIES + 3;
|
|
pvals[3] = PAX_val32(dp->kmdbtc * 1000);
|
|
double btcfactor;
|
|
//if ( time(NULL) > BTCFACTOR_TIMESTAMP )
|
|
btcfactor = .00001;
|
|
//else btcfactor = .001;
|
|
pvals[4] = PAX_val32(dp->btcusd * btcfactor);
|
|
pvals[5] = PAX_val32(dp->CNYUSD);
|
|
sprintf(fname,"/%s/.komodo/komodofeed",userhome);
|
|
if ( (fp= fopen(fname,"wb")) != 0 )
|
|
{
|
|
for (i=1; i<MAX_CURRENCIES+6; i++)
|
|
iguana_rwnum(1,&data[i*sizeof(uint32_t)],sizeof(*pvals),(void *)&pvals[i]);
|
|
pvals[0] = calc_crc32(0,(void *)&data[sizeof(uint32_t)],(MAX_CURRENCIES+5)*sizeof(*pvals));
|
|
iguana_rwnum(1,data,sizeof(*pvals),(void *)&pvals[0]);
|
|
if ( fwrite(data,sizeof(*pvals),MAX_CURRENCIES+6,fp) != MAX_CURRENCIES+6 )
|
|
printf("error writing pvals to (%s)\n",fname);
|
|
fclose(fp);
|
|
}
|
|
if ( dispflag != 0 )
|
|
{
|
|
for (i=0; i<6; i++)
|
|
printf("%u ",pvals[i]);
|
|
printf("KMD %.8f BTC %f CNY %f (%f) btcusd pval.%u\n",dp->kmdbtc,dp->btcusd,dp->CNYUSD,1./dp->CNYUSD,pvals[4]);
|
|
}
|
|
}
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
void PAX_init()
|
|
{
|
|
static int32_t didinit; //double commission = 0.;
|
|
if ( didinit == 0 )
|
|
{
|
|
init_Currencymasks();
|
|
//calc_smooth_code(127,7);
|
|
//tradebot_monitorall(0,0,0,0,"fxcm",commission);
|
|
//tradebot_monitorall(0,0,0,0,"truefx",commission);
|
|
//tradebot_monitorall(0,0,0,0,"instaforex",commission);
|
|
exchange_create("PAX",0);
|
|
didinit = 1;
|
|
}
|
|
}
|
|
|