Browse Source

tradebots

release/v0.1
jl777 9 years ago
parent
commit
3396c3f852
  1. 4
      iguana/exchanges777.h
  2. 8
      iguana/iguana_exchanges.c
  3. 205
      iguana/iguana_tradebots.c
  4. 4
      includes/iguana_apideclares.h

4
iguana/exchanges777.h

@ -49,7 +49,7 @@ struct exchange_info
char name[16],apikey[MAX_JSON_FIELD],apisecret[MAX_JSON_FIELD],tradepassword[MAX_JSON_FIELD],userid[MAX_JSON_FIELD];
uint32_t exchangeid,pollgap,lastpoll;
uint64_t lastnonce; double commission;
CURL *cHandle; queue_t requestQ,pricesQ,pendingQ[2];
CURL *cHandle; queue_t requestQ,pricesQ,pendingQ[2],tradebotsQ;
};
void *curl_post(void **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3);
@ -58,6 +58,8 @@ char *instantdex_sendcmd(struct supernet_info *myinfo,cJSON *argjson,char *cmdst
char *exchanges777_Qprices(struct exchange_info *exchange,char *base,char *rel,int32_t maxseconds,int32_t allfields,int32_t depth,cJSON *argjson,int32_t monitor,double commission);
struct exchange_info *exchanges777_info(char *exchangestr,int32_t sleepflag,cJSON *json,char *remoteaddr);
char *exchanges777_unmonitor(struct exchange_info *exchange,char *base,char *rel);
void tradebot_timeslice(struct exchange_info *exchange,void *bot);
char *exchanges777_Qtrade(struct exchange_info *exchange,char *base,char *rel,int32_t maxseconds,int32_t dotrade,int32_t dir,double price,double volume,cJSON *argjson);
void prices777_processprice(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth);
#endif

8
iguana/iguana_exchanges.c

@ -24,7 +24,7 @@ struct exchange_request
struct queueitem DL;
cJSON *argjson; char **retstrp;
double price,volume,hbla,lastbid,lastask,commission;
uint64_t orderid; uint32_t timedout;
uint64_t orderid; uint32_t timedout,expiration;
int32_t dir,depth,func,numbids,numasks;
char base[32],rel[32],destaddr[64],invert,allflag,dotrade;
struct exchange_quote bidasks[];
@ -474,7 +474,8 @@ char *exchanges777_process(struct exchange_info *exchange,int32_t *retvalp,struc
void exchanges777_loop(void *ptr)
{
int32_t flag,retval; struct exchange_request *req; char *retstr; struct exchange_info *exchange = ptr;
struct exchange_info *exchange = ptr;
int32_t flag,retval; struct exchange_request *req; char *retstr; void *bot;
while ( 1 )
{
flag = retval = 0;
@ -511,6 +512,8 @@ void exchanges777_loop(void *ptr)
}
}
}
if ( (bot= queue_dequeue(&exchange->tradebotsQ,0)) != 0 )
tradebot_timeslice(exchange,bot);
if ( flag == 0 && time(NULL) > exchange->lastpoll+exchange->pollgap )
{
if ( (req= queue_dequeue(&exchange->pricesQ,0)) != 0 )
@ -668,6 +671,7 @@ struct exchange_info *exchange_create(char *exchangestr,cJSON *argjson)
exchange->issue = funcs[i];
iguana_initQ(&exchange->pricesQ,"prices");
iguana_initQ(&exchange->requestQ,"request");
iguana_initQ(&exchange->tradebotsQ,"tradebots");
iguana_initQ(&exchange->pendingQ[0],"pending0");
iguana_initQ(&exchange->pendingQ[1],"pending1");
exchange->exchangeid = exchangeid;

205
iguana/iguana_tradebots.c

@ -15,6 +15,146 @@
#include "exchanges777.h"
#define TRADEBOTS_GAPTIME 60
struct tradebot_trade
{
double price,volume;
uint64_t orderid;
uint32_t started,finished,dir;
char exchangestr[32],base[32],rel[32];
};
struct tradebot_info
{
struct queueitem DL;
struct supernet_info *myinfo;
char name[128],exchangestr[32],base[32],rel[32];
int32_t dir,numtrades,estimatedtrades;
double price,volume,pricesum,totalvolume;
uint32_t dead,pause,started,expiration;
struct tradebot_trade trades[];
};
cJSON *tradebot_json(struct supernet_info *myinfo,struct exchange_info *exchange,struct tradebot_info *bot)
{
char str[64]; int32_t i,numpending; double pendsum,pendvolume,vol; cJSON *json,*array,*item;
json = cJSON_CreateObject();
jaddstr(json,"exchange",exchange->name);
jaddstr(json,"started",utc_str(str,bot->started));
if ( bot->pause != 0 )
jaddstr(json,"paused",utc_str(str,bot->pause));
if ( bot->dead != 0 )
jaddstr(json,"stopped",utc_str(str,bot->dead));
jaddstr(json,"base",bot->base);
jaddstr(json,"rel",bot->rel);
jaddstr(json,"type",bot->dir > 0 ? "buy" : "sell");
jaddnum(json,"price",bot->price);
jaddnum(json,"volume",bot->volume);
if ( (vol= bot->totalvolume) > SMALLVAL )
{
jaddnum(json,"aveprice",bot->pricesum/vol);
jaddnum(json,"totalvolume",vol);
}
array = cJSON_CreateArray();
for (pendsum=pendvolume=numpending=i=0; i<bot->numtrades; i++)
{
item = cJSON_CreateObject();
jadd64bits(item,"orderid",bot->trades[i].orderid);
jaddstr(item,"type",bot->trades[i].dir > 0 ? "buy" : "sell");
jaddstr(item,"base",bot->trades[i].base);
jaddstr(item,"rel",bot->trades[i].rel);
jaddnum(item,"price",bot->trades[i].price);
jaddnum(item,"volume",bot->trades[i].volume);
jaddstr(item,"started",utc_str(str,bot->trades[i].started));
if ( bot->trades[i].finished == 0 )
{
jaddnum(item,"elapsed",time(NULL) - bot->trades[i].started);
pendsum += bot->trades[i].price * bot->trades[i].volume;
pendvolume += bot->trades[i].volume;
numpending++;
} else jaddnum(item,"duration",bot->trades[i].finished - bot->trades[i].started);
jaddi(array,item);
}
jadd(json,"trades",array);
if ( (vol= pendvolume) > SMALLVAL )
{
jaddnum(json,"pending",numpending);
jaddnum(json,"pendingprice",pendsum/vol);
jaddnum(json,"pendingvolume",vol);
}
return(json);
}
struct tradebot_info *tradebot_find(struct exchange_info *exchange,char *botname)
{
struct tradebot_info PAD,*bot,*retbot = 0;
memset(&PAD,0,sizeof(PAD));
queue_enqueue("tradebotsQ",&exchange->tradebotsQ,&PAD.DL,0);
while ( (bot= queue_dequeue(&exchange->tradebotsQ,0)) != 0 && bot != &PAD )
{
if ( strcmp(botname,bot->name) == 0 )
retbot = bot;
queue_enqueue("tradebotsQ",&exchange->tradebotsQ,&bot->DL,0);
}
return(retbot);
}
struct tradebot_info *tradebot_create(struct supernet_info *myinfo,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume,int32_t duration)
{
struct tradebot_info *bot;
if ( (bot= calloc(1,sizeof(*bot))) != 0 )
{
bot->myinfo = myinfo;
safecopy(bot->exchangestr,exchange->name,sizeof(bot->exchangestr));
safecopy(bot->base,base,sizeof(bot->base));
safecopy(bot->rel,rel,sizeof(bot->rel));
bot->dir = dir, bot->price = price, bot->volume = volume;
bot->started = (uint32_t)time(NULL);
if ( duration < 1 )
duration = 1;
bot->expiration = bot->started + duration;
bot->estimatedtrades = (duration / TRADEBOTS_GAPTIME) + 1;
sprintf(bot->name,"%s_%s_%s.%d",exchange->name,base,rel,bot->started);
queue_enqueue("tradebotsQ",&exchange->tradebotsQ,&bot->DL,0);
}
return(bot);
}
struct tradebot_trade *tradebot_issuetrade(struct exchange_info *exchange,struct tradebot_info *bot,char *base,char *rel,double price,double volume,int32_t dir)
{
struct tradebot_trade *tr; char *str; int32_t maxseconds = 30,dotrade = 1;
bot = realloc(bot,sizeof(*bot) + (bot->numtrades + 1) * sizeof(bot->trades[0]));
tr = &bot->trades[bot->numtrades++];
memset(tr,0,sizeof(*tr));
tr->price = price, tr->volume = volume, tr->dir = dir;
safecopy(tr->exchangestr,exchange->name,sizeof(tr->exchangestr));
safecopy(tr->base,base,sizeof(tr->base));
safecopy(tr->rel,rel,sizeof(tr->rel));
if ( (str= exchanges777_Qtrade(exchange,base,rel,maxseconds,dotrade,dir,price,volume,0)) != 0 )
free(str);
return(tr);
}
void tradebot_timeslice(struct exchange_info *exchange,void *_bot)
{
double volume; struct tradebot_info *bot = _bot;
if ( time(NULL) < bot->expiration && bot->dead == 0 )
{
if ( bot->pause == 0 )
{
if ( bot->numtrades == 0 || bot->trades[bot->numtrades-1].finished != 0 || time(NULL) > bot->trades[bot->numtrades-1].started+60 )
{
if ( bot->estimatedtrades > 0 )
{
volume = bot->volume / bot->estimatedtrades;
tradebot_issuetrade(exchange,bot,bot->base,bot->rel,bot->price,volume,bot->dir);
}
}
}
queue_enqueue("tradebotsQ",&exchange->tradebotsQ,&bot->DL,0);
} else free(bot);
}
#include "../includes/iguana_apidefs.h"
@ -40,21 +180,78 @@ THREE_STRINGS(tradebot,unmonitor,exchange,base,rel)
} else return(clonestr("{\"error\":\"tradebots only local usage!\"}"));
}
THREE_STRINGS_AND_THREE_DOUBLES(tradebot,accumulate,exchange,base,rel,price,volume,duration)
char *tradebot_launch(struct supernet_info *myinfo,char *exchangestr,char *base,char *rel,int32_t dir,double price,double volume,int32_t duration,char *remoteaddr,cJSON *json)
{
struct exchange_info *exchange;
if ( remoteaddr == 0 )
{
return(clonestr("{\"result\":\"start accumulating\"}"));
if ( (exchange= exchanges777_info(exchangestr,1,json,remoteaddr)) != 0 )
{
if ( tradebot_create(myinfo,exchange,base,rel,1,price,fabs(volume),duration) != 0 )
return(clonestr("{\"result\":\"tradebot created\"}"));
else return(clonestr("{\"error\":\"couldnt create exchange tradebot\"}"));
} else return(clonestr("{\"error\":\"couldnt find/create exchange info\"}"));
} else return(clonestr("{\"error\":\"tradebots only local usage!\"}"));
}
THREE_STRINGS_AND_THREE_DOUBLES(tradebot,divest,exchange,base,rel,price,volume,duration)
char *tradebot_control(char *exchangestr,char *botid,int32_t control,char *remoteaddr,cJSON *json)
{
struct tradebot_info *bot; struct exchange_info *exchange;
if ( remoteaddr == 0 )
{
return(clonestr("{\"result\":\"start divesting\"}"));
if ( (exchange= exchanges777_info(exchangestr,1,json,remoteaddr)) != 0 )
{
if ( (bot= tradebot_find(exchange,botid)) != 0 )
{
if ( control > 1 )
bot->pause = (uint32_t)time(NULL);
else if ( control == 0 )
bot->pause = 0;
else bot->dead = (uint32_t)time(NULL);
return(clonestr("{\"result\":\"ask bot to pause\"}"));
} else return(clonestr("{\"error\":\"cant find tradebot\"}"));
}
else return(clonestr("{\"error\":\"couldnt find/create exchange info\"}"));
} else return(clonestr("{\"error\":\"tradebots only local usage!\"}"));
}
THREE_STRINGS_AND_THREE_DOUBLES(tradebot,accumulate,exchange,base,rel,price,volume,duration)
{
return(tradebot_launch(myinfo,exchange,base,rel,1,price,volume,duration,remoteaddr,json));
}
THREE_STRINGS_AND_THREE_DOUBLES(tradebot,divest,exchange,base,rel,price,volume,duration)
{
return(tradebot_launch(myinfo,exchange,base,rel,-1,price,volume,duration,remoteaddr,json));
}
TWO_STRINGS(tradebot,status,exchange,botid)
{
struct tradebot_info *bot; struct exchange_info *ptr;
if ( remoteaddr == 0 )
{
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
{
if ( (bot= tradebot_find(ptr,botid)) != 0 )
return(jprint(tradebot_json(myinfo,ptr,bot),1));
}
}
return(clonestr("{\"error\":\"tradebots only local usage!\"}"));
}
TWO_STRINGS(tradebot,pause,exchange,botid)
{
return(tradebot_control(exchange,botid,1,remoteaddr,json));
}
TWO_STRINGS(tradebot,stop,exchange,botid)
{
return(tradebot_control(exchange,botid,-1,remoteaddr,json));
}
TWO_STRINGS(tradebot,resume,exchange,botid)
{
return(tradebot_control(exchange,botid,0,remoteaddr,json));
}
#include "../includes/iguana_apiundefs.h"

4
includes/iguana_apideclares.h

@ -42,6 +42,10 @@ TWOSTRINGS_AND_TWOHASHES_AND_TWOINTS(InstantDEX,confirm,reference,message,basetx
THREE_STRINGS_AND_DOUBLE(tradebot,monitor,exchange,base,rel,commission);
THREE_STRINGS(tradebot,unmonitor,exchange,base,rel);
TWO_STRINGS(tradebot,status,exchange,botid);
TWO_STRINGS(tradebot,pause,exchange,botid);
TWO_STRINGS(tradebot,stop,exchange,botid);
TWO_STRINGS(tradebot,resume,exchange,botid);
THREE_STRINGS_AND_THREE_DOUBLES(tradebot,accumulate,exchange,base,rel,price,volume,duration);
THREE_STRINGS_AND_THREE_DOUBLES(tradebot,divest,exchange,base,rel,price,volume,duration);

Loading…
Cancel
Save