Earlier quoted context omitted.
To go a step further, I don't think you should be required to talk to middlemen when buying stocks, yet here we are. The house wants its cut.
Central counterparty concept implemented by most exchanges is a valid service, as otherwise counterparty risk management would be a nightmare - an example of a useful “middleman”.
C++ patterns for low-latency applications including high-frequency trading
171–180 of 240 posts
Re: C++ patterns for low-latency applications including high-frequency trading
#172Earlier quoted context omitted.
Very anecdotal but of the people I know in game studios who are tasked with engine work, and people who make a killing doing FPGA work for HFT firms, both camps shook their head at Casey’s HMH thing. Uniformly I do not know of a single professional developer of this sort of caliber who looked at HMH and thought it looks great. Quite the opposite. I think they found his approach and justifications unsound as it would…
Casey's a fundamentalist, in the religious extremist sense. Just as a theologian might have something to learn from the most extremely devout, so it is that there is valuable information in Casey's proselytizing. But you should no more follow Casey in form and function than you would any other fundamentalist.
The religious comparison is also a telling one given the state of the industry; for we aren't the theologian, we're the common folk looking for someone or something to follow in order to write better code.
Who are Casey's alternatives? Gesturing the cppcon as a learning resource has "read research papers to learn about a field" vibes. They can be highly informative and worth the effort, but not for beginners.
Who are Casey's contemporaries? If he's a fundamentalist then the atheists are nowhere to be seen by the beginners. Instead we have agile ceremony shamans, clean code bible missionaries, tdd doomsday cults, oop/rust/haskell/etc. zealots, a thriving megachurch industry of Lambda schools, and the mother of all cargo cults masquerading as web dev.
Re: C++ patterns for low-latency applications including high-frequency trading
#173Earlier quoted context omitted.
Let me preface by noting that I don't necessarily disagree with any part of what you wrote. However, there are design patterns that exceed the guardrails you're thinking of, and those are the patterns that benefit the most from shared_ptr. Typically, they involve fine- to medium-grained objects, particularly those that have dynamic state (meaning by-value copies are not an option.) An example might be a FlightAware-l…
> Let's simplify by assuming that planes are in the sky forever and don't get added or removed. If planes are around forever, wouldn't you be better off interning them? e.g. having a single global std::vector (or std::array ) and passing around offsets in that array? And your PlaneVec would just be a glorified std::vector (or int)? I don't see any value in maintaining a reference count if you're never intending to cl…
Definitely not. :) I added that restriction just to sidestep the need to add and remove planes to/from existing Updaters and Views. Besides, you might have an Updater for US flights and one for European ones, and a View might span worldwide Delta flights or just US ones. Updaters and Views might come and go dynamically. The reference counting is key.
In this example, it doesn't matter when Planes get cleaned up, but it does matter that they do. A better alternative than the one you're proposing would be to just use vector and leak the planes, but that's crappy for different reasons (e.g. long-term memory usage and it would bar Plane from, say, RAII-owning its own log file.)
Re: C++ patterns for low-latency applications including high-frequency trading
#174Earlier quoted context omitted.
It's not that simple. It could just be that exchange is the first one to drop to 99 but all others will as well.
Yeah I gather that is the expectation, but if you are the first to execute an order you will sell that order at the old 100 price before it lowers. You are fighting for making an order before the information spreads to the other bots. (Right?!)
"Making" has specific meaning as well, and I don't think it's what you're trying to say.
Re: C++ patterns for low-latency applications including high-frequency trading
#175Earlier quoted context omitted.
> obviously good trades Are you able to expand with any examples of this?
There are really two schools of approach to this. On one hand you have quantitatively driven strategies that try to predict either a price or direction based on various inputs. Here you’re mostly focused on predictive accuracy, and the challenge is in exiting the trade at the right time. This is where a lot of the speed comes into play (what is your predictive horizon, and can you act fast enough to take advantage of…
Re: C++ patterns for low-latency applications including high-frequency trading
#176Earlier quoted context omitted.
I briefly looked over your stock exchange code: - For memory management, consider switching to std::shared_ptr. It won't slow anything down and will put that concern to rest entirely. - For sockets, there are FOSS libraries that will outperform your code and save you a ton of headaches dealing with caveats and annoyances. For example, your looping through FD_ISSET is slower than e.g. epoll or kqueue. - For dependenci…
I did not know std::shared_ptr would not slow things down. I've learned something new today! :) Yes, I agree, epoll is a lot better than FD_ISSET. Maybe I can keep moving with my C++ code but do people still trust C++ projects anymore? My ideal use case is a hobbyist who wants a toy stock exchange to run directly in AWS. I felt that C++ has a lot of bad publicity and if I want anyone to trust/try my code I would have…
C++ gets bad publicity only from evangelists of the flavour of the month of self-described "successor of C++". They don't have a sales pitch beyond "C++ bad" and that's what they try to milk.
And yet the world runs on C++.
Re: C++ patterns for low-latency applications including high-frequency trading
#177Earlier quoted context omitted.
There are really two schools of approach to this. On one hand you have quantitatively driven strategies that try to predict either a price or direction based on various inputs. Here you’re mostly focused on predictive accuracy, and the challenge is in exiting the trade at the right time. This is where a lot of the speed comes into play (what is your predictive horizon, and can you act fast enough to take advantage of…
Isn't there challenges with slippage and managing the volumes while exiting? And isn't speed also about processing the data feed as fast as possible to time the exit decisions accurately?
The market mechanics trades tend to have no recoverability if you miss the opportunity, so you’re often trading out in error and it’s a matter of trying to stem the loss on a position that you do not have an opinionated value signal on.
And there’s definitely an angle to inbound processing speed for both styles of trading, with differing levels of sensitivity depending on the time horizons you are attempting to predict or execute against. Using the example above again, detecting the arb opportunity and firing quickly is obviously paramount, but if you’re running a strategy where you have a 1 minute predictive time horizon sure, there’s some loss that can be associated with inefficiency if you aren’t moving quickly and someone else is firing at a similar signal, but generally speaking there’s enough differentiation in underlying alpha between you and any competitors that the sensitivity to absolute speed isn’t as prevalent as most people expect.
Basically it boils down to going fast enough to beat the competition, and if there isn’t any you have all the time in the world to make decisions and act on them.
Re: C++ patterns for low-latency applications including high-frequency trading
#178Earlier quoted context omitted.
I'm curious how HFT relates to pro audio programming. The timescale is close to gaming (usually It's not hard real-time like you're going to crash your car, but if you miss your deadline it causes an unacceptable and audible glitch. I've always been a bit surprised that Jane Street uses OCaml. I know they've put a lot of attention into the GC, but it still seems fundamentally indeterminate in a way that would make mo…
Audio has a lot of buffering behaviour that you wouldn't generally see in event-reactive HFT. Think of all the plugins that you know of that have non-zero latency, compressors with 'lookahead' etc. There are maybe some similarities where the logic is more complex (loop unrolling, SIMD and so on) but I feel like plugins are generally optimizing for throughput (CPU usage) and quality (oversampling etc) rather than pure…
Put another way, audio is operating on a much longer timescale, but cares a lot about worst-case latency (as well as throughput and quality). Is that true of HFT also, or are they more concerned with average latency? If computing a trade takes too long, can they just discard it, or is it catastrophic to miss that deadline?
Re: C++ patterns for low-latency applications including high-frequency trading
#179Earlier quoted context omitted.
> Why do we pass by value when sharing ownership? Because it allows for move semantics, so that you give the caller to option to make a copy, which bumps up the reference count, or to entirely avoid any copy whatsoever, which allows transfering ownership without bumping the reference count. What if the callee sometimes wants to get a reference count and sometimes doesn't? In the latter case, your proposed signature f…
> If you pass > foo(shared_ptr const&) > you incur an extra pointer chase in the callee. Actually this is usually not the case (assuming of course that caller is holding the original pointer in a shared_ptr which is the use case we were discussing.) That shared_ptr instance is held either on the stack (with address FP + offset or SP + offset) or inside another object (typically 'this' + offset.) To call foo(const sha…
You're overthinking it. Think in cache lines. No matter what the instructions say, with all their fancy addressing modes, foo has to load two cache lines: one holding the shared_ptr and another holding the pointee data. If we instead passed bar* in a register, we'd need to grab only one cache line: the pointee's.
Sure. Maybe the caller already has a fully formed shared_ptr around somewhere but not in cache. Maybe foo often doesn't access the pointee. But how often does this situation arise?
Re: C++ patterns for low-latency applications including high-frequency trading
#180Earlier quoted context omitted.
> If you pass > foo(shared_ptr const&) > you incur an extra pointer chase in the callee. Actually this is usually not the case (assuming of course that caller is holding the original pointer in a shared_ptr which is the use case we were discussing.) That shared_ptr instance is held either on the stack (with address FP + offset or SP + offset) or inside another object (typically 'this' + offset.) To call foo(const sha…
> That shared_ptr instance is held either on the stack (with address FP + offset or SP + offset) or inside another object (typically 'this' + offset.) To call foo(const shared_ptr &), the compiler adds the base pointer and offset together, then passes the result of that addition - without dereferencing it. You're overthinking it. Think in cache lines. No matter what the instructions say, with all their fancy addressi…
The cache doesn't make a difference here. To clarify: we start with a shared_ptr instance. It must get dereferenced to be used. It must either be dereferenced by the caller (the const bar & contract) or by the callee (the const shared_ptr & contract).
If the caller dereferences it, it might turn out to be superfluous if the callee wasn't actually going to use it. In this case const shared_ptr & is more efficient.
However, if the caller happened to have already dereferenced it prior to the call, one dereferencing would be avoided. In this case const bar & is more efficient.
> Sure. Maybe the caller already has a fully formed shared_ptr around somewhere but not in cache.
This is where our misunderstanding is. The caller starts out by only having a shared_ptr. Someone (caller or callee) has to dig the bar * out.