NexusFi: Find Your Edge


Home Menu

 





High Frequency Trading Adventures with Rithmic's R API


Discussion in Trading Journals

Updated
      Top Posters
    1. looks_one iantg with 3 posts (13 thanks)
    2. looks_two Fi with 1 posts (0 thanks)
    3. looks_3 DavidHP with 1 posts (1 thanks)
    4. looks_4 imadaitelarabi with 1 posts (1 thanks)
    1. trending_up 6,283 views
    2. thumb_up 15 thanks given
    3. group 5 followers
    1. forum 5 posts
    2. attach_file 1 attachments




 
Search this Thread
  #1 (permalink)
 iantg 
charlotte nc
 
Experience: Advanced
Platform: My Own System
Posts: 409 since Jan 2015
Thanks Given: 91
Thanks Received: 1,152

INTRO / BACKSTORY
This will be a technical Journal dedicated to sharing and discussing some of the technical details behind a trading system I developed with the R|API class library. I would have killed to have found some resources for this back when I started, so I am sharing a few things for anyone else looking to get into this type of thing.

I am still working out some bugs and optimizations, but it's up and running. I'd love to have a second set of eyes on some of the technical stuff, hence the main reason I am sharing.

First: Here is some information from Rithmic on their R|API: https://yyy3.rithmic.com/?page_id=9

Basically this is a class library that you can use to build your own trading system, and do pretty much anything you would like. Why would anyone do this? The main use case is speed. By cutting out all the bloat of charts, plug-ins, Dom's, etc. and keeping the code to a minimum, you can achieve speeds far beyond the reach of any retail software. Combined this with Rithmic's colocation in Arora, and certain types of high frequency trading are possible.

For my strategy I need low latency, but not ultra low latency. I have been working Rithmic and Matt and Jake at Optimus for a few months to get everything up and running.

I am in the very late stages of fine tuning some of the performance aspects of the system, so I figured I would put some stuff out here and see what people think. With that out of the way, let's get into it!

PART 1: MULTI-THREADING

Rithmic's API has a lot of events that can run concurrently. So any bottle neck in one place can cause a bottle neck in another if you are on a single thread. So to this end I came up with the following high level design.




Basically we have two main feeds that run between the application and the exchange.

1. The main data feed that provides bid / ask price updates
2. The main messaging feed that provides order state changes: (Fills, Cancels, etc.)

Each of these feeds need to run with nearly 100% up time, so the calculation intensive work is pawned off on threads in the thread pool.

*** The first point where I am conflicted is with respect to the order routing. My current design has a small but simple Alpha signal detector that picks up either true or false right after new prices come in. From here, I stay on the main thread and send out orders and cancel any unwanted orders. My thinking is that in terms of speed / performance, there is little to nothing that matters more than how fast I can get my orders out the door, so I should in theory stay on the main thread. But the counter argument is that by running anything on the main thread other than the feeds, I can bottle necking future feed events from registering as quickly as possible.

This will be the first topic I punt for discussion.

My next post I will get into the code a little.

Ian


In the analytical world there is no such thing as art, there is only the science you know and the science you don't know. Characterizing the science you don't know as "art" is a fools game.
Visit my NexusFi Trade Journal Started this thread Reply With Quote

 
Best Threads (Most Thanked)
in the last 7 days on NexusFi
Sober Journey With S&P
24 thanks
2026 Jlab journal
10 thanks
Lady Vols Primer: Trading Volatility Journal
7 thanks
Algo automated / semi-automated trading anyone?
6 thanks
Trying to learn Volume and price action correlation
5 thanks
  #2 (permalink)
 iantg 
charlotte nc
 
Experience: Advanced
Platform: My Own System
Posts: 409 since Jan 2015
Thanks Given: 91
Thanks Received: 1,152

CODE BASICS

To start off here is how the main data feed works: (Basically there are 2 things I care about from the bid and ask feeds, the price and the time.
I collect the data and send it to a task method that stays on the main thread for a few lines, then hops onto a thread in the thread pool to process the rest...

public override void BestAskQuote(AskInfo oInfo)
{
Bid = oInfo.Price +-.25;
Ask =oInfo.Price;
TimeStamp =oInfo.Ssboe;
MicroSeconds = oInfo.Usecs;

Task1(Bid,Ask,TimeStamp,MicroSeconds);
}

public override void BestAskQuote(AskInfo oInfo)
{
Bid = oInfo.Price;
Ask =oInfo.Price +.25;
TimeStamp =oInfo.Ssboe;
MicroSeconds = oInfo.Usecs;

Task1(Bid,Ask,TimeStamp,MicroSeconds);
}


public static void Task1(double Bid, double Ask, double PT, double SL, int TimeStamp, int MicroSeconds)
{
// If the Buy Alpha signal is true, jump into the Main method and place a buy order
if (Alpha_L == true)
{
Program.Main(new String[] { "B"});
}
// If the Sell Alpha signal is true, jump into the Main method and place a sell order
if (Alpha_S == true)
{
Program.Main(new String[] { "S"});
}
// Now hop of the main thread and continue processing more complex things. I have two tasks queued up, if one is currently running I will use the other.

if (!PTTask1_L.IsCompleted)
{
if (PTTask2_L.IsCompleted)
{
PTTask2_L = Task.Run(() =>
{
MCB.PT_Hit_L("P2", Bid, Ask, PT + PTadj, PT + -SLadj, Count_L, LEF_MIN, LS, PT, SL, TimeStamp, NanoTime, nowEvent, askcount, Min2);
});
}
}
else
{
PTTask1_L = Task.Run(() =>
{
MCB.PT_Hit_L("P1", Bid, Ask, PT + PTadj, PT + -SLadj, Count_L, LEF_MIN, LS, PT, SL, TimeStamp, NanoTime, nowEvent, askcount, Min2);
});
}

}


TOPIC: CONCURRENT TASKS
This next topic is also an area where I don't know if I am fully optimized or not. There are 3 approaches to handling tasks, they each have some cons.

1. Option 1. Use one predefined task only: This will make it easy to follow the lineage of your code, and avoid any possible duplicate events, but if the task is already in use when it gets called, you will either be too late, or if you force the application to wait for the task to complete, you are introducing latency into your code that can be avoided by other approaches.

2. Task.Run(() => with no predefined task: This will get rid of any potential bottle necks from waiting on a task, but if you hit this block of code over and over by mistake, you will just queue up task after task and potentially end up with duplicates and have no good lineage to trace back from. For initial debugging I decided this was a bad approach, and haven't really pivoted back to this.

3. Create two tasks, and default to run Task1, but if Task1 is busy, then run Task2. From what I have seen Task1 usually get's called 95% of the time. For now, this is the approach I have been going with. It does add a few extra lines of code and require some extra steps to kick things off, but I can trace the lineage anytime I need, and avoid endless duplicates in case something goes wrong.

I have a section of my code that fires every named task during the start up so that the default state of every task will have a value and not be null, so I don't have to add lines to do a null check before looking into their state.


I"ll put up some more stuff as I can think of it, but if anyone wants to see anything specific or has any questions or insights please feel free to respond.

Ian


In the analytical world there is no such thing as art, there is only the science you know and the science you don't know. Characterizing the science you don't know as "art" is a fools game.
Visit my NexusFi Trade Journal Started this thread Reply With Quote
Thanked by:
  #3 (permalink)
imadaitelarabi
Morocco Marrakech
 
Posts: 1 since Aug 2022
Thanks Given: 0
Thanks Received: 0


Hello I am Imad , a Trader who is interested in algorithmic trading.

I read your post about Rithmic API! and i am interesting to know some information about Rithmic System and how HFT trading is working on it!

So basically if you use this Rithmic API , do you will still be affected with slippage?


I have a strategy which is working with stop orders for entries and trailing stops , can that be coded and run with R API ?

Thank you , waiting for your reply my freind


Reply With Quote
  #4 (permalink)
 
Fi's Avatar
 Fi 
NexusFi
 


imadaitelarabi View Post
So basically if you use this Rithmic API, do you will still be affected with slippage? I have a strategy which is working with stop orders for entries and trailing stops, can that be coded and run with R API?

@imadaitelarabi,

Welcome to NexusFi, Imad\! Great questions. Let me break them down:

Slippage

Using Rithmic's API does not eliminate slippage -- no API does. Slippage is a function of market liquidity, volatility at the moment of execution, and your order type. What Rithmic does do is reduce the latency between your order and the exchange, which means less time for the market to move against you. Their standard R|API+ runs around 250 microseconds. Their Diamond API (built for HFT) connects directly to exchange-facing gateways and gets even faster.

The key thing to understand: your stop orders trigger as market orders, so some slippage is inherent to how stops work. That is true regardless of what platform or API you use.

Stop Orders & Trailing Stops

Yes, fully supported. R|API+ provides server-side trailing stops, bracket orders, and OCO orders. Server-side means they stay active even if your local application disconnects -- important for reliability. You can configure trailing stops with tick offsets, set targets, and use auto-cancel timers.

Development Path

The native API uses C++ and C#. There are also Python wrappers (like async_rithmic) that use the Protocol API over WebSockets if you prefer Python. Be aware that Rithmic's architecture is event-driven (subscription-notification model), and you will need to handle multi-threading -- data feeds and order management should run on separate threads. You will also need to pass conformance testing before going live.

One honest note: Rithmic's documentation is sparse. Community resources like the threads here on NexusFi from members like @iantg (who built an HFT system on R|API) will be some of your best references.

TGIF! Have a good weekend!

-- Fi

"The API doesn't eliminate slippage -- it just stops you from being the last one to know about it."


Learn more about Fi AI trading companion
IMPORTANT: I can make mistakes! Always verify data before relying on it.

Please leave feedback here. You can disable my ability to reply to your posts by placing me on your ignore list.

Fi provides educational information on a best-effort basis only. You are responsible for your own trading decisions and for verification of all data. This message is not trading advice.
Reply With Quote
  #5 (permalink)
 iantg 
charlotte nc
 
Experience: Advanced
Platform: My Own System
Posts: 409 since Jan 2015
Thanks Given: 91
Thanks Received: 1,152

I haven't visited this forum for a few years, but after getting tagged in few things, and seeing this old blog, I wanted to give a quick update. The code snippets and original design I shared are pretty wrong and dated based on all the changes I have made over the years. For anyone wanting to get into this retail HFT/MFT space here is what you should know, and the biggest lessons I can share.

1. RAPI has a single main thread that runs everything. So you need to get off of that main thread as fast as possible and use it as sparingly as possible. All your order state callbacks, and market data events will fire on the same linear thread. So if you add junk code to run a lot of calculations, and do stuff, you will block, create a backlog and add significant latency to everything. You really need to get outside of the box if you want to optimize this. Running a secondary data feed on a different thread that you control can eliminate the market data entirely. Then you just have to be very selective about which order state events you run and what you do. It's best to just send stuff to queues, and hop off and let other threads run all your calculations in parallel, this way you scale horizonallly instead of creating a virtical log jam.

2. You will need to move to Linux if you want to get fast. Windows can only do so much, but Linux has some knobs you can play with that windows doesn't have. The whole C# v C++ thing doesn't matter as much as just clearing the processing queue fast and getting packets to your server as fast as possible.

3. Co-location is a game of whack-o-mole. You can get inside Aurora on a 1-2 core VPS for 100 to 300 dollars, but you will choke on a heavy load every time. You won't have enough cores to scale, and you will end up with extreme tail latency, but your mean latency can look nice if the market is slow. Going to Chicago and getting a bare metal server was the best path for me. I have a couple servers there and with my data feeds and and all my costs I am just under $600 dollars a month in fixed cost. To get two servers with the same specs in Aurora would be 3x to 5x as much and really only make a difference for me with my tail latency. I am not really trying to compete in the < 1 millisecond game. I just need to be < 10 milliseconds tick to trade 75% of the time or better for my specific edge to work.

4. There are some esoteric edges out there that retail traders can execute in the retail HFT/MFT space, but they are an absolute pain in the ass to get off the ground. I spent more time dealing with wash trade issues, regulatory bullshit, bad brokers/clearing companies, and their bad risk management systems than I spent working on the actual edge last year. Sending a bracket order and having both the profit target and stop loss fill sounds like it shouldn't be possible right? And if so, it sounds like the exchange, the broker or clearing company made a whoopsie, because surely an FOCCA bracket order sent on a mature platform couldn't lead to this.... But it does very often, and they will blame you if you end up with a wash trade and take no responsibility for the failure of their internal systems that are suppose to manage FOCCA orders.

5. Speeds are decent, but you won't get 250 microseconds unless you are in Aurora, and even then, you won't get that unless you were on Rithmic's private Diamond API. The thing is retail trades aren't getting anywhere near the Diamond API because it takes a huge bankroll, and ILInk, DMA, and dedicated risk management. So in reality, your best bet is to sit in Chicago on a bare metal server and get the market data in 2-3 millseconds, and another 2-3 millseconds back to send the order. That is realistically the best you will get in terms of predictable, stable speeds. Trying to run an algo during the US cash open on a VPS in Aurora - you will run 1-5 seconds behind real time, the entire first 1-5 seconds every time. If your system is trading think books at 3:00 am, then maybe a VPS will work for you, but for anyone looking to trade normal hours on normal products, you are basically going to get killed unless you have plenty of cores and know what you are doing.

6. Databento is your best friend. These guys are great and their tech is the best a retail trader can get. But for the best results you will want to run both Databento and Rithmic on two seperate producer / consumer models and then merge them into one unabridged feed - taking whichever is fastest packet by packet. This trick alone cut my tail latency down more than anything else I tried, and I tried everything.... I spent 2 months trying to crack a kernel bypass of the RAPI which has like a dozen gotchas, but finally got it to work - and gained basically nothing. The TLDR: Your packets will eat more latency just getting to your server than you can shave off by doing any fancy processing. It's best to just have multiple data feeds, merge them and take whichever packet is fastest.

Anyway, that's about it. Maybe I will share more in a few years if something interesting worth sharing comes up.

Ian


In the analytical world there is no such thing as art, there is only the science you know and the science you don't know. Characterizing the science you don't know as "art" is a fools game.
Visit my NexusFi Trade Journal Started this thread Reply With Quote
Thanked by:
  #6 (permalink)
 
DavidHP's Avatar
 DavidHP 
Isla Mujeres, MX
Legendary Market Wizard
 
Experience: Advanced
Platform: NinjaTrader
Broker: Ninjatrader / Optimus Futures / AmpFutures
Trading: NQ / ES / 6E / 6B / CL
Frequency: Every few days
Duration: Minutes
Posts: 1,802 since Aug 2009
Thanks Given: 11,742
Thanks Received: 3,018


iantg View Post
I haven't visited this forum for a few years, but after getting tagged in few things, and seeing this old blog, I wanted to give a quick update. The code snippets and original design I shared are pretty wrong and dated based on all the changes I have made over the years. For anyone wanting to get into this retail HFT/MFT space here is what you should know, and the biggest lessons I can share.



1. RAPI has a single main thread that runs everything. So you need to get off of that main thread as fast as possible and use it as sparingly as possible. All your order state callbacks, and market data events will fire on the same linear thread. So if you add junk code to run a lot of calculations, and do stuff, you will block, create a backlog and add significant latency to everything. You really need to get outside of the box if you want to optimize this. Running a secondary data feed on a different thread that you control can eliminate the market data entirely. Then you just have to be very selective about which order state events you run and what you do. It's best to just send stuff to queues, and hop off and let other threads run all your calculations in parallel, this way you scale horizonallly instead of creating a virtical log jam.



2. You will need to move to Linux if you want to get fast. Windows can only do so much, but Linux has some knobs you can play with that windows doesn't have. The whole C# v C++ thing doesn't matter as much as just clearing the processing queue fast and getting packets to your server as fast as possible.



3. Co-location is a game of whack-o-mole. You can get inside Aurora on a 1-2 core VPS for 100 to 300 dollars, but you will choke on a heavy load every time. You won't have enough cores to scale, and you will end up with extreme tail latency, but your mean latency can look nice if the market is slow. Going to Chicago and getting a bare metal server was the best path for me. I have a couple servers there and with my data feeds and and all my costs I am just under $600 dollars a month in fixed cost. To get two servers with the same specs in Aurora would be 3x to 5x as much and really only make a difference for me with my tail latency. I am not really trying to compete in the < 1 millisecond game. I just need to be < 10 milliseconds tick to trade 75% of the time or better for my specific edge to work.



4. There are some esoteric edges out there that retail traders can execute in the retail HFT/MFT space, but they are an absolute pain in the ass to get off the ground. I spent more time dealing with wash trade issues, regulatory bullshit, bad brokers/clearing companies, and their bad risk management systems than I spent working on the actual edge last year. Sending a bracket order and having both the profit target and stop loss fill sounds like it shouldn't be possible right? And if so, it sounds like the exchange, the broker or clearing company made a whoopsie, because surely an FOCCA bracket order sent on a mature platform couldn't lead to this.... But it does very often, and they will blame you if you end up with a wash trade and take no responsibility for the failure of their internal systems that are suppose to manage FOCCA orders.



5. Speeds are decent, but you won't get 250 microseconds unless you are in Aurora, and even then, you won't get that unless you were on Rithmic's private Diamond API. The thing is retail trades aren't getting anywhere near the Diamond API because it takes a huge bankroll, and ILInk, DMA, and dedicated risk management. So in reality, your best bet is to sit in Chicago on a bare metal server and get the market data in 2-3 millseconds, and another 2-3 millseconds back to send the order. That is realistically the best you will get in terms of predictable, stable speeds. Trying to run an algo during the US cash open on a VPS in Aurora - you will run 1-5 seconds behind real time, the entire first 1-5 seconds every time. If your system is trading think books at 3:00 am, then maybe a VPS will work for you, but for anyone looking to trade normal hours on normal products, you are basically going to get killed unless you have plenty of cores and know what you are doing.



6. Databento is your best friend. These guys are great and their tech is the best a retail trader can get. But for the best results you will want to run both Databento and Rithmic on two seperate producer / consumer models and then merge them into one unabridged feed - taking whichever is fastest packet by packet. This trick alone cut my tail latency down more than anything else I tried, and I tried everything.... I spent 2 months trying to crack a kernel bypass of the RAPI which has like a dozen gotchas, but finally got it to work - and gained basically nothing. The TLDR: Your packets will eat more latency just getting to your server than you can shave off by doing any fancy processing. It's best to just have multiple data feeds, merge them and take whichever packet is fastest.



Anyway, that's about it. Maybe I will share more in a few years if something interesting worth sharing comes up.



Ian

Welcome back.
I don't HFT and most of this I don't understand, but I've enjoyed your posts on Nexusfi.

Thank you


Rejoice in the Thunderstorms of Life . . .
Knowing it's not about Clouds or Wind. . .
But Learning to Dance in the Rain ! ! !
Follow me on X Reply With Quote
Thanked by:




Last Updated on March 28, 2026


© 2026 NexusFi®, s.a., All Rights Reserved.
Av Ricardo J. Alfaro, Century Tower, Panama City, Panama, Ph: +507 833-9432 (Panama and Intl), +1 888-312-3001 (USA and Canada)
All information is for educational use only and is not investment advice. There is a substantial risk of loss in trading commodity futures, stocks, options and foreign exchange products. Past performance is not indicative of future results.
About Us - Contact Us - Site Rules, Acceptable Use, and Terms and Conditions - Downloads - Top
no new posts