<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Programming &#8211; The Financial Hacker</title>
	<atom:link href="https://financial-hacker.com/tag/programming/feed/" rel="self" type="application/rss+xml" />
	<link>https://financial-hacker.com</link>
	<description>A new view on algorithmic trading</description>
	<lastBuildDate>Wed, 31 Jan 2024 10:07:48 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://financial-hacker.com/wp-content/uploads/2017/07/cropped-mask-32x32.jpg</url>
	<title>Programming &#8211; The Financial Hacker</title>
	<link>https://financial-hacker.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Trading with REST</title>
		<link>https://financial-hacker.com/crypto-trading-with-rest-part-1/</link>
					<comments>https://financial-hacker.com/crypto-trading-with-rest-part-1/#comments</comments>
		
		<dc:creator><![CDATA[jcl]]></dc:creator>
		<pubDate>Mon, 17 Oct 2022 11:16:41 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Bittrex]]></category>
		<category><![CDATA[Broker]]></category>
		<category><![CDATA[Hacking]]></category>
		<guid isPermaLink="false">https://financial-hacker.com/?p=4517</guid>

					<description><![CDATA[Many brokers and exchanges can nowadays be accessed online with a REST API that communicates with plain-text HTTP requests. The days of awkward proprietary broker APIs are coming to an end. This article is a step by step instruction of implementating a REST API interface in C for connecting a trading system to the Bittrex &#8230; <a href="https://financial-hacker.com/crypto-trading-with-rest-part-1/" class="more-link">Continue reading<span class="screen-reader-text"> "Trading with REST"</span></a>]]></description>
										<content:encoded><![CDATA[
<p>Many brokers and exchanges can nowadays be accessed online with a REST API that communicates with plain-text HTTP requests. The days of <a href="https://financial-hacker.com/dear-brokers/" target="_blank" rel="noopener">awkward proprietary broker APIs</a> are coming to an end. This article is a step by step instruction of implementating a REST API interface in C for connecting a trading system to the <a href="https://global.bittrex.com/" target="_blank" rel="noopener">Bittrex cryptocurrency exchange.</a> It&#8217;s for the <a href="https://zorro-project.com" target="_blank" rel="noopener">Zorro platform</a>, but the principles are also valid for other exchanges and platforms. The C code for a basic REST API implementation is relatively short and straightforward. <span id="more-4517"></span></p>
<p> For connecting the Zorro platform to a particular broker API, a DLL must be dropped in its Plugin folder. The DLL is then automatically recognized and appears in Zorro&#8217;s Broker selection box. For trading with the broker, the DLL exports functions for getting prices and sending orders. These functions are standardized and described in the <a href="https://zorro-project.com/manual/en/brokerplugin.htm" target="_blank" rel="noopener">Zorro manual</a>. They are the same for all brokers. The following 4 functions are the most important:</p>
<p><strong>BrokerOpen</strong> &#8211; identify the DLL.<br /><strong>BrokerLogin</strong> &#8211; initialize and store login credentials.<br /><strong>BrokerAsset</strong> &#8211; retrieve price and other parameters of an asset.<br /><strong>BrokerBuy2</strong> &#8211; send a buy or sell order.</p>
<p>These four are sufficient for running most trading strategies. The DLL can export additional functions that are useful, but not mandatory, since Zorro works around them when they are not implemented:</p>
<p><strong>BrokerAccount</strong> -get the account state.<br /><strong>BrokerTrade</strong> &#8211; get the trade or order state.<br /><strong>BrokerHistory2</strong> -get price history.<br /><strong>BrokerCommand</strong> &#8211; set special modes, get order book, etc.</p>
<p>Zorro users have written DLLs for several broker APIs, but the code is often redundant and invents the wheel many times again. I&#8217;ll give here an example of a relatively lean broker DLL that can be used as template for individual REST API implementations. Bittrex is a US based digital currency exchange that supports several hundred crypto currencies and provides free API access. We&#8217;re first going to implement the 4 mandatory functions, following the API description on the Bittrex website:</p>
<p><a href="https://bittrex.github.io/api/v3" target="_blank" rel="noopener">https://bittrex.github.io/api/v3</a></p>
<p>We will use the free Visual C++ Community Edition from Microsoft. Aside from the exported functions, we need some internal functions to print messages, send HTTP requests, parse a JSON response, and generate a digital signature. For all this there&#8217;s ready code available on the Internet, but there are also ready functions in Zorro&#8217;s library. To make life easier, we simply import the <a href="https://zorro-project.com/manual/en/funclist.htm" target="_blank" rel="noopener">Zorro function library</a> to the DLL. The VC++ setup for generating such a DLL is described here:</p>
<p><a href="https://zorro-project.com/manual/en/dlls.htm#project" target="_blank" rel="noopener">https://zorro-project.com/manual/en/dlls.htm</a></p>
<p>The setup is for a C++ trading strategy, but works as well for a broker API DLL. First we&#8217;re going to implement the adminstrative stuff, the <strong>BrokerOpen</strong> and <strong>BrokerLogin</strong> functions:</p>
<pre class="prettyprint">#define PLUGIN_TYPE 2<br />#define PLUGIN_NAME "Bittrex V3"<br />#define DLLFUNC extern "C" __declspec(dllexport)<br /><br />int (__cdecl *BrokerMessage)(const char *Text);<br />int (__cdecl *BrokerProgress)(const int Progress);<br />...<br /><br />DLLFUNC int BrokerOpen(char* Name,FARPROC fpMessage,FARPROC fpProgress)<br />{<br />  strcpy_s(Name,32,PLUGIN_NAME);<br />  (FARPROC&amp;)BrokerMessage = fpMessage;<br />  (FARPROC&amp;)BrokerProgress = fpProgress;<br />  return PLUGIN_TYPE;<br />}</pre>
<p>The <strong>BrokerOpen</strong> function is Zorro specific. It sets up two function pointers for printing message and sending heartbeats to Zorro. It&#8217;s needed for recognizing the DLL in the <strong>Plugin</strong> folder and letting the plugin name, &#8220;Bittrex V3&#8221;, appear in the broker scrollbox. </p>
<p>Next we need the login function that&#8217;s called at the begin and the end of any algo trading session</p>
<pre class="prettyprint">struct GLOBAL {<br />  int PriceType,VolType,OrderType;<br />  double Unit; // smallest trade unit<br />  char Path[256]; // send path buffer<br />  char Key[256],Secret[256]; // credentials<br />  char Symbol[64],Uuid[256]; // last trade symbol and UUID<br />  char AccountId[16]; // account currency<br />} G; // parameter singleton<br />...<br /><br />DLLFUNC int BrokerLogin(char* User,char* Pwd,char* Type,char* Accounts)<br />{<br />  if(User) { // login<br />    memset(&amp;G,0,sizeof(G));<br />    strcpy_s(G.Key,User);<br />    strcpy_s(G.Secret,Pwd);<br />    return 1;<br />  } else  // logout<br />    return 0;<br />}</pre>
<p>This function only sets up the <strong>G</strong> struct, a singleton that holds all global variables of the DLL. The <strong>User</strong> and <strong>Pwd</strong> arguments contain the Bittrex key and secret. They are taken from the Zorro login fields or from the account list. <strong>Type</strong> is the account type, ignored here because Bittrex has no demo accounts.  <strong>Account</strong> is the account identifier and also ignored since we&#8217;re not using sub-accounts.</p>
<p>Next comes the function to retrieve prices and other parameters of a particular cryptocurrency. It&#8217;s a bit more complex and requires a HTTP request to the API. Some requests require authentication, some not. For all this we first implement a <strong>send()</strong> function in the DLL that uses Zorro&#8217;s functions for sending <a href="https://zorro-project.com/manual/en/http.htm" target="_blank" rel="noopener">http requests</a> and generating a <a href="https://zorro-project.com/manual/en/hmac.htm" target="_blank" rel="noopener">HMAC signature</a>. The authentication method by the Bittrex REST API V3 is a bit complex:</p>
<p><em>To properly sign an authenticated request for the Bittrex v3 API, the following headers must be included: Api-Key, Api-Timestamp, Api-Content-Hash, Api-Signature. <span style="font-size: revert;">Api-Timestamp is </span>the current time as a UNIX timestamp in epoch-millisecond format. <span style="font-size: revert;">Api-Content-Hash </span>is a SHA512 hash of the request body, Hex-encoded (with no request body, a SHA512 hash of an empty string). For creating the Api-Signature, first generate a string by concatenating the following items: Contents of the Api-Timestamp header; the full URI used to make the request, including query string; the HTTP method of the request, in all caps (GET, POST, DELETE, etc.); Contents of the Api-Content-Hash header. Sign this string via HmacSHA512, using the API secret as the signing secret. Hex-encode the result and populate the Api-Signature header with it.</em></p>
<p>This is the implementation:</p>
<pre class="prettyprint">#define RHEADER "https://api.bittrex.com/v3/"<br />...<br /><br />int sleep(int ms)<br />{<br />  Sleep(ms); <br />  return BrokerProgress(0);<br />}<br /><br />char* send(const char* Url,<br />  int Mode = 0,<br />  const char* Method = NULL,<br />  const char* Body = NULL)
{
  static char Url[1024], Header[2048], Signature[1024],
    Buffer1[1024*1024], Buffer2[2048];
  *Signature = *Header = 0;
  sprintf_s(Url,"%s%s",RHEADER,Url);
  if (Mode &amp; 1) { // Authentication required
    strcpy_s(Header, "Content-Type:application/json");
    strcat_s(Header, "\nAccept:application/json");
    strcat_s(Header, "\nApi-Key: ");
    strcat_s(Header,G.Key);
    strcat_s(Header, "\nApi-Timestamp: ");
    __time64_t Time; _time64(&amp;Time);
    static __time64_t Offset = 0;
    char* TimeStamp = i64toa(Time*1000 + Offset++); 
    strcat_s(Header, TimeStamp);
    strcat_s(Header, "\nApi-Content-Hash: ");
    char* Hash = hmac(Body, 0, 0, 512);
    strcat_s(Header,Hash);
    strcpy_s(Signature, TimeStamp);
    strcat_s(Signature, Url);
    if(Method &amp;&amp; *Method)
      strcat_s(Signature, Method);
    else if(!Body)
      strcat_s(Signature,"GET");
    else
      strcat_s(Signature,"POST");
    strcat_s(Signature, Hash);
    strcat_s(Header, "\nApi-Signature: ");
    strcat_s(Header, hmac(Signature, 0, G.Secret, 512));
  }

  char* Response = Mode &amp; 2? Buffer2 : Buffer1;<br />  int MaxSize = Mode &amp; 2? sizeof(Buffer2) : sizeof(Buffer1);<br />  int Id = http_request(Url,Body,Header,Method);
  if(!Id) goto send_error;
// wait 30 seconds for the server to reply
  int Size = 0, Wait = 3000;  
  while (!(Size = http_status(Id)) &amp;&amp; --Wait &gt; 0)
    if(!sleep(10)) goto send_error;
  if (!Size) goto send_error;
  if(!http_result(Id,Response,MaxSize)) goto send_error;
  Response[MaxSize-1] = 0; // prevent buffer overrun
  http_free(Id);
  return Response;
<br />// transfer unsuccessful?
send_error:
  if(Id) http_free(Id);
  return NULL;
}
</pre>
<p>The above code adds an authentication header with signature when <strong>Mode</strong> == 1. <strong>Mode == 2</strong> selects a second, smaller response buffer and thus allows to evaluate two API responses at the same time. The <strong>sleep</strong> function generates a delay with a heartbeat to keep the Zorro window responsive during long requests. If it returns <strong>0</strong>, someone has hit Zorro&#8217;s [Stop] key and all operations should be aborted. The Windows <strong>_time64</strong> function has only 1-second resolution, so we add an incremented <strong>Offset</strong> for generating unique timestamps.</p>
<p>We&#8217;re now prepared to implement the <strong>BrokerAsset</strong> function:</p>
<pre class="prettyprint">double fixAmount(double Value)<br />{<br />  int Exp = log10(Value);<br />  if (Exp &gt;= 0) Exp++;<br />  return pow(10,Exp);<br />}<br /><br />DLLFUNC int BrokerAsset(char* Symbol,double* pPrice,double* pSpread,<br />double *pVolume, double *pPip, double *pPipCost, double *pMinAmount,<br />double *pMargin, double *pRollLong, double *pRollShort, double *pCommission)<br />{<br />  sprintf_s(G.Url,"markets/%s/ticker",fixSymbol(Symbol));<br />  char* Response = send(G.Url,2);<br />  if(!Response) return 0;<br />  double Bid = strvar(Response, "bidRate", 0.),<br />    Ask = strvar(Response,"askRate",0.);<br />  if (Ask &gt; 0. Bid &gt; 0. &amp;&amp; pSpread) <br />    *pSpread = Ask - Bid;<br />  double Last = strvar(Response, "lastTradeRate", 0.);<br />  if(Ask == 0. || G.PriceType == 2) <br />    Ask = Last;<br />  if (Ask == 0.) return 0; // symbol does not exist<br />  if(pPrice) *pPrice = Ask;<br />  if(pVolume) {<br />    sprintf_s(G.Url,"markets/%s/summary",fixSymbol(Symbol));<br />    Response = send(G.Url,2);<br />    if (Response) {<br />      if (G.VolType == 4)<br />        *pVolume = strvar(Response, "volume", 0);<br />    else<br />        *pVolume = strvar(Response, "quoteVolume", 0);<br />    }<br />  }<br />  if (pMinAmount) { // get lot amount<br />    sprintf_s(G.Url,"markets/%s",fixSymbol(Symbol));<br />    Response = send(G.Url,2);<br />    if (Response) {<br />      *pMinAmount = fixAmount(strvar(Response,"minTradeSize",0.000001));<br />      if (pPip) {<br />        int Exp = strvar(Response,"precision",8);<br />        *pPip = pow(10,-Exp); <br />        while (*pPip * *pMinAmount &lt; 0.000000001)<br />         *pPip *= 10; // avoid too small pip cost<br />        if (pPipCost)<br />          *pPipCost = *pPip * *pMinAmount;<br />      }<br />    }<br />  }<br />  if (pMargin) <br />    *pMargin = -100; // no leverage<br />  return 1;<br />} </pre>
<p>This function is supposed to return current price, current ask-bid spread, and current volume. It can also optionally request other asset specific parameters when available from the API. Otherwise Zorro will replace them with parameter values from the asset list. Broker APIs rarely provide all requested parameters. Make sure to only calculate and fill a parameter when its pointer passed to the function is nonzero. Most of the pointers are NULL most of the time.</p>
<p>The <strong>send</strong> function uses the second buffer because we&#8217;ll need price requests internally for calculating the account state. For getting lot amount, pip size, and pip cost, two more API requests are needed. The values from the response string are parsed with Zorro&#8217;s <strong>strvar</strong> function. The <strong>fixAmount</strong> function converts a value to its next-higher power of 10 &#8211; for instance, 7 is converted to 10 and 0.07 to 0.1. We&#8217;re doing this because we don&#8217;t want a strange number for the lot amount. The pip size is calculated from the precision, but we prevent it from going too small. Bittrex has no leverage, so the margin cost is always 100%.    </p>
<p>The next and final function sends an order to the API:</p>
<pre class="prettyprint">DLLFUNC int BrokerBuy2(char* Symbol,int Volume,double StopDist,double Limit,double *pPrice,int *pFill)<br />{<br />  if(!isConnected() || !Volume) return 0;<br /><br />// compose the body<br />  char Body[256] = "{\n";<br />  strcat_s(Body,"\"marketsymbol\": \"");<br />  strcat_s(Body,fixSymbol(Symbol));<br />  strcat_s(Body,"\",\n\"direction\": \"");<br />  strcat_s(Body,Volume &gt; 0? "BUY" : "SELL");<br />  strcat_s(Body,"\",\n\"type\": \"");<br />  strcat_s(Body,Limit &gt; 0. ? "LIMIT" : "MARKET");<br />  strcat_s(Body,"\",\n\"quantity\": \"");<br />  double Size = labs(Volume);<br />  if(G.Amount &lt; 1.) Size *= G.Amount;<br />  strcat_s(Body,ftoa(Size));<br />  if (Limit &gt; 0.) {<br />    strcat_s(Body,"\",\n\"limit\": \"");<br />    strcat_s(Body,ftoa(Limit));<br />  }<br />  strcat_s(Body,"\",\n\"timeInForce\": \"");<br />  if ((G.OrderType&amp;2) &amp;&amp; Limit &gt; 0.) <br />    strcat_s(Body,"GOOD_TIL_CANCELLED"); // limit orders only<br />  else if (G.OrderType&amp;1) <br />    strcat_s(Body,"FILL_OR_KILL"); // fill all or nothing<br />  else <br />    strcat_s(Body,"IMMEDIATE_OR_CANCEL");<br />  strcat_s(Body,"\"\n}");<br /><br />  char* Response = send("orders",1,0,Body);<br />  if(!Response) return 0;<br /><br />  char* Uuid = strtext(Response,"id","");<br />  if(!*Uuid) return 0; // failed<br />  strcpy(G.Uuid,Uuid);<br />  double Filled = strvar(Response,"fillQuantity",0);<br />  if(Filled == 0. &amp;&amp; !(G.OrderType&amp;2))<br />    return 0; // unfilled FOK/IOC order<br />  double Price = strvar(Response,"proceeds",0);<br />  if (Filled &gt; 0. &amp;&amp; Price &gt; 0. &amp;&amp; pPrice)<br />    *pPrice = Price/Filled;<br />  if (*pFill) *pFill = Filled/min(1.,G.Unit);<br />  return -1; <br />}</pre>
<p>The function first composes a message body in this JSON format (example):</p>
<pre>{<br /><span class="hljs-attr">  "marketSymbol"</span>: <span class="hljs-string">"ETH/BTC"</span>,<br /><span class="hljs-attr">  "direction"</span>: <span class="hljs-string">"BUY"</span>,<br /><span class="hljs-attr">  "type"</span>: <span class="hljs-string">"LIMIT"</span>,<br /><span class="hljs-attr">  "quantity"</span>: <span class="hljs-string">"0.1"</span>,<br /><span class="hljs-attr">  "limit"</span>: "0.008<span class="hljs-string">"</span>,<br /><span class="hljs-attr">  "timeInForce"</span>: "IMMEDIATE_OR_CANCEL<span class="hljs-string">"</span><br />}</pre>
<p>If the order is accepted, the response has this JSON format:</p>
<pre>{<br />  "id": "12345-6789-007-4711",<br />  "marketSymbol": "ETH/BTC",<br />  "direction": "BUY",<br />  "type": "LIMIT",<br />  "quantity": "0.1",<br />  "limit": "0.008",<br />  "timeInForce": "IMMEDIATE_OR_CANCEL",<br />  "fillQuantity": "0.05",<br />  "commission": "0.000002",<br />  "proceeds": "0.00001",<br />  "status": "<span class="json-property-enum" title="Possible values"><span class="json-property-enum-item">CLOSED</span></span>"<br />}</pre>
<p>The relevant fields, especially the id, the fill amount, and the fill price, are parsed from the response and returned. The return value <strong>-1</strong> indicates to Zorro that the order generated no identifer number, but an UUID. It was stored and can be retrieved with a subsequent command. <strong>G.Unit </strong>is the lot amount that was generated with the previous <strong>BrokerAsset</strong> call. </p>
<p>The remaining functions not described here &#8211; <strong>BrokerTrade</strong>, <strong>BrokerAccount</strong>, <strong>BrokerHistory2</strong>, and <strong>BrokerCommand</strong> &#8211;  are implemented in a similar way. You can find them in the full source code in the <strong>Source</strong> folder of the latest Zorro version. </p>
<p><strong>Update, November 2023:</strong> Bittrex recently announced that they will terminate their operation. So the Bittrex API plugin described herein lost its purpose, but you can still use the code as a template for connecting Zorro to any other broker or crypto exchange APIs &#8211; at least as long as they remain operational.  </p>
]]></content:encoded>
					
					<wfw:commentRss>https://financial-hacker.com/crypto-trading-with-rest-part-1/feed/</wfw:commentRss>
			<slash:comments>12</slash:comments>
		
		
			</item>
	</channel>
</rss>
