11
$\begingroup$

I'd like to connect Mathematica with my Italian electronic trading platform.

To connect I need to open a TCP socket client towards the trading platform and send a string command.

The high-level description (pseudo code) is like this:

- create new tcp socket on hostname="localhost and port ="5333"
- create out channel
- create input channel

- send request in string format 
   "function=subscribe|item=<stockCode>|schema=ask1;bid1;last_price"

- read response: if response is like outcom=OK then wait the push update

- read push update  

- close socket

But how I can do this with Mathematica?

Using JLink I should write something like this:

socket = new Socket(TCP_address, TCP_port);
out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(),
"UTF-8"));
in = new BufferedReader(new InputStreamReader(socket.getInputStream(),
"UTF-8"));
//send request to T3 .
out.println(messagge);
//Wait response 
String response = in.readLine();
//[...]
//If response is outcome=OK wait push data
while(true){
String update = in.readLine();
//Thread to manage push data
}
} catch (UnknownHostException e) {
//[...]
} catch (IOException e) {
//[...]
}
//[...]

But I'd like to know if is possible to avoid java and .net !

$\endgroup$
9
  • $\begingroup$ What do you mean by "create out channel" and "create input channel"? Is this something different than what one gets anyway with a TCP socket? $\endgroup$ Commented Jun 12, 2013 at 11:08
  • $\begingroup$ @OleksandrR. -- Often in these types of applications one may want high speed throughput, so one doesn't want two way traffic on a TCP socket. $\endgroup$
    – Jagra
    Commented Jun 12, 2013 at 11:34
  • $\begingroup$ This sounds like a job for JLink $\endgroup$
    – Jagra
    Commented Jun 12, 2013 at 11:35
  • 1
    $\begingroup$ @msalese May I ask you what is the purpose of this connection? I mean, I'm really interested in real applications for Mathematica in the Finance field. Please share more information with us, because the topic is very interesting! $\endgroup$
    – Rod
    Commented Jun 14, 2013 at 14:02
  • 1
    $\begingroup$ Ok, I'm a retail option trader (buy side), what I need is to avoid DDE in Excel and use tcp from Mathematica to get realtime bid/ask. Bid/ask is used then to calibrate Implied Volatility Function. I would like to use excel only as GUI tool and let mathKernel to handle data (from the broker) and computation. Excel is connected to mathKernel through excelLink: wolfram.com/products/applications/excel_link $\endgroup$
    – msalese
    Commented Jun 17, 2013 at 8:10

2 Answers 2

11
$\begingroup$

I recently discovered SocketLink bundled with Mathematica. It's not documented, but super straightforward:

<< "SocketLink`"
port = 1234;
s = CreateClientSocket["host", port]
{inputStream, outputStream} = OpenSocketStreams[s];

This returns a binary InputStream and OutputStream that you can read/write like any other Mathematica stream with BinaryRead and BinaryWrite.

Edit: Highlighting @pickett's comment about the documented features available in 10.3 and later: Mathematica 10.3 new Network Programming Features. (SocketLink is available in at least 10.0.2 and perhaps earlier.)

$\endgroup$
3
  • 2
    $\begingroup$ There is also the new networking functionality that the OP refers to here, i.e. SocketConnect and friends. $\endgroup$
    – C. E.
    Commented Nov 17, 2015 at 0:42
  • $\begingroup$ Thanks for pointing that out -- somehow I didn't find that after a while of searching. $\endgroup$
    – ZachB
    Commented Nov 17, 2015 at 0:53
  • $\begingroup$ mathematica.stackexchange.com/questions/98462/… $\endgroup$
    – msalese
    Commented Apr 19, 2016 at 12:19
10
$\begingroup$

Here is my sample code using JLink. It's not a foolproof code, but if someone know haw to do better, please let me know.

The following code let Mathematica connect with T3Open Trading Software (Italian Broker WeBank), it expose some api that you can call with tcp socket. In this example I'm going to pass a list of options code (Terna Call) and take the ask/bid price.

Needs["JLink`"];
InstallJava[];

t3OpenRequest [exchange_, market_, code_, schema_] := Module[
  {funSub, request, unsub, tcpaddress, tcpport, socket, out, in, 
   response},
  response = {};
  funSub = "function=subscribe|item=";
  unsub = "function=unsubscribe";
  (*ip addess and port where T3Open is running*)
  tcpaddress = "192.168.0.78";
  tcpport = 5333;
  (*build the string request to send*)
  request = 
   StringJoin[{funSub, exchange, ".", market, ".", code, "|schema=", 
     schema}];
  (*create a Socket object*)
  socket = JavaNew["java.net.Socket", tcpaddress, tcpport];
  out = JavaNew["java.io.PrintWriter", socket@getOutputStream[], True];
  in = JavaNew["java.io.BufferedReader", 
    JavaNew["java.io.InputStreamReader", socket@getInputStream[]]];
  (*send the request*)
  out@println[request];
  (*read the first response*)
  in@readLine[];
  (*read the second response, here are the data that I need*)
  response = Append[response , in@readLine[]];
  (*usubscribe the service*)
  out@println[unsub];
  (*close the socket*)
  socket@close[];
  Take[Flatten[StringSplit[response, "|"]], -1]
  ]

To use the function I prepare the options code list:

In[4]:= codeList01 = {{791308., 791309., 791310., 791311., 791312., 
   791313., 791314., 791315., 791316., 791317., 791318., 
   791319.}, {"TRN3G2.90", "TRN3G3", "TRN3G3.10", "TRN3G3.20", 
   "TRN3G3.30", "TRN3G3.40", "TRN3G3.50", "TRN3G3.60", "TRN3G3.70", 
   "TRN3G3.80", "TRN3G3.90", "TRN3G4"}}

Out[4]= {{791308., 791309., 791310., 791311., 791312., 791313., 
  791314., 791315., 791316., 791317., 791318., 791319.}, {"TRN3G2.90",
   "TRN3G3", "TRN3G3.10", "TRN3G3.20", "TRN3G3.30", "TRN3G3.40", 
  "TRN3G3.50", "TRN3G3.60", "TRN3G3.70", "TRN3G3.80", "TRN3G3.90", 
  "TRN3G4"}}

In[5]:= codeList02 = Transpose[codeList01]

Out[5]= {{791308., "TRN3G2.90"}, {791309., "TRN3G3"}, {791310., 
  "TRN3G3.10"}, {791311., "TRN3G3.20"}, {791312., 
  "TRN3G3.30"}, {791313., "TRN3G3.40"}, {791314., 
  "TRN3G3.50"}, {791315., "TRN3G3.60"}, {791316., 
  "TRN3G3.70"}, {791317., "TRN3G3.80"}, {791318., 
  "TRN3G3.90"}, {791319., "TRN3G4"}}

And here call the function using Table on all options:

In[10]:= data = 
 Table[t3OpenRequest["MI", "DER", ToString[code], schema], {code, 
   codeList02[[All, 1]]}, {schema, {"best_ask1", "best_bid1"}}]

Out[10]= {{{"0.0"}, {"0.0"}}, {{"0.1825"}, {"0.1405"}}, {{"0.089"}, \
{"0.0805"}}, {{"0.0325"}, {"0.027"}}, {{"0.0085"}, {"0.004"}}, \
{{"0.003"}, {"0.0005"}}, {{"0.003"}, {"0.0005"}}, {{"0.0015"}, \
{"0.0005"}}, {{"0.0015"}, {"0.0005"}}, {{"0.0"}, {"0.0"}}, {{"0.0"}, \
{"0.0"}}, {{"0.0"}, {"0.0"}}}

In[11]:= data01 = ToExpression[Flatten[data]]

Out[11]= {0., 0., 0.1825, 0.1405, 0.089, 0.0805, 0.0325, 0.027, \
0.0085, 0.004, 0.003, 0.0005, 0.003, 0.0005, 0.0015, 0.0005, 0.0015, \
0.0005, 0., 0., 0., 0., 0., 0.}

Here the couples of ask and bid:

In[12]:= data02 = Partition[data01, 2]

Out[12]= {{0., 0.}, {0.1825, 0.1405}, {0.089, 0.0805}, {0.0325, 
  0.027}, {0.0085, 0.004}, {0.003, 0.0005}, {0.003, 0.0005}, {0.0015, 
  0.0005}, {0.0015, 0.0005}, {0., 0.}, {0., 0.}, {0., 0.}}
$\endgroup$
1
  • 2
    $\begingroup$ now that you proofed that this is working it is maybe time to clean up your code a bit. avoid magic numbers inside your function (use options instead) and maybe move the whole thing into a package. $\endgroup$
    – Stefan
    Commented Jun 28, 2013 at 13:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.