I now think there’s another reason that SIG, Bloomberg, LiquidNet and other employers didn’t make me an offer even though I passed technical screening.
In our chats, I used the generic term "didn’t like my face" as an umbrella term for several different factors. Today I want to mention a new factor – "what if this candidate takes my offer and continues to shop around?"
I believe some companies don’t like that risk. When they make an offer the want to ensure the candidate will accept. They want to see "Hey we are clearly the favorite in his mind and he is in a hurry. If we make him an offer he will likely accept right away."
Clearly, I’m not that type of candidate. I often come across as a "job shopper", through my non-verbal language or even through my explicit verbal answers. For example, when asked "Why are you looking to change job" I often answer "I’m actually doing fine on my current job but there are better opportunities like the role in your company."
So, please beware of the subtle signals you send to interviewers.
Here’s my answer to the question:
Well, the major challenge in my project is understanding the non-trivial legacy codebase. Once we reach sufficient understanding, it’s often relatively straightforward to implement the required change in a "pinhole surgery".
You could say that analysis is 50% of the effort and design, testing, debugging constitute 45% of the effort and code change is no more than 5%.
The percentage can vary depending on the type of change. Analysis could be 30 to 70% of the effort. Frequently, the moment we figure out how things work, we get that Aha moment and the problem is basically solved.
In terms of source code change, as a team we work hard to minimize code change in favor of config change, but there are some exceptions —
* I often need to add logging in my local codebase
* I did make bug fixes.
I also need to read lots of code as part of analysis.
- There are multi-leg FIX orders to trade two stocks without options
- I believe there’s no valid multi-leg order to trade the same stock using market orders. The multiple legs simply collapse to one. How about two-leg limit orders? I would say Please split into two disconnected limit orders.
- There are multi-leg FIX orders to trade two futures contracts
- There are multi-leg FIX orders to trade 3 products like a butterfly.
- There are multi-leg FIX orders with a special ratio like an option “ratio spread”
But today I show a more common multi-leg strategy order — buy 5 buy-write with IBM. At least four option exchanges support multi-leg FIX orders — Nasdaq-ISE / CBOE / ARCA / Nasdq-PHLX
38=5; // quantity = 5 units
555=2; // how many legs in this order. This tag precedes a repeatingGroup!
654=Leg1; //leg id for one leg
600=IBM; // same value repeated later!
608=OC; //OC=call option
610=201007; //option expiry
612=85; //strike price
624=2; //side = Sell
Note that in this case, the entire strategy is defined in FIX, without reference to some listed symbol or productID.
First let’s talk about custom containers. GDB would show the field names of an object, but frequently not the values. I guess integers values might show up but more than half the fields are pointers ( actually char-array field would be easy to print.)
If I call a function on the object, I have to be very lucky and very careful. q(->) has never worked for me so far, so I need to use q(*) to de-reference every pointer before calling a method on the pointee, and pray it works.
http://www.yolinux.com/TUTORIALS/src/dbinit_stl_views-1.03.txt works on std::map …
A simple experiment using https://github.com/tiger40490/repo1/blob/cpp1/cpp/88miscLang/containerDumpOperator.cpp
- g++ -g theFile.cpp && gdb -iex ‘add-auto-load-safe-path .’ ./a.out
- (gdb) print *(li._M_impl._M_start+1) # can print 2nd element if it’s std::string or double
- Note before vector initialization, gdb already shows the addresses inside the vector, but some addresses are not populated. Just retry after the initialization.
- std::unordered_map is doable:
- (gdb) print **(tm._M_buckets) # prints first pair in a hash table bucket
- (gdb) print *((**(tm._M_buckets))._M_next) # next pair in the same bucket
- std::map content is harder
- (gdb) print *(int*)(tm._M_t._M_impl._M_header._M_left+1) # prints one key
- (gdb) print *(int*)(tm._M_t._M_impl._M_header._M_right+1) # prints another key in the pair
- (gdb) print *(int*)((void*)(tm._M_t._M_impl._M_header._M_right+1)+sizeof(int)) #prints the value in the pair.
- the (void*) is needed before we add sizeof(value_type). Without the cast, the pointer arithmetic would be different.
- from the key field to value field, we move by 4 bytes (i.e. sizeof value_type) from 0x6050e0 to 0x6050e4. It’s actually easy to manually type .. print *0x6050e4
- I suspect the _M_right pointer is seated at the “color” field. Increment to the key field?
Most pthreads programs don’t retrieve the return value via pthread_join().
https://stackoverflow.com/questions/3692591/return-versus-pthread-exit-in-pthread-start-functions has a comment by the author of boost::thread (reference implementation for c++11 thread library). He said
(3) I never use the return value of a thread in raw POSIX threads. However, I tend to use higher level facilities such as the Boost thread library, and more recently the C++0x thread library, which provide alternative means for transferring values between threads such as futures, which avoid the problems associated with memory management that you allude to.
Therefore, even though you felt it was unnatural to store the per-thread computed results in a global array, in practice it’s not bad. It is inherently thread-safe because there’s no data sharing, in a truly parallel mode.
That was my preferred solution, but to experiment, I also used new to return a value to pthread_join(). Personally, I am always wary of using new() in one function and the corresponding delete() in another function … unreliable. As much as possible, I use smart pointers to manage new/delete.
https://github.com/tiger40490/repo1/edit/cpp1/cpp/thr/parallelSum_Pimco.cpp shows both solutions
A few learning points.
The Object.clone() implementation is not that important, because I should always override it in my class like Pen, but here are some observations about this Object.clone():
- shallow copy, not deep copy, not very useful.
- this protected method is mostly meant to be invoked by a subclass:
- If your variable points to some Pen object that’s no Clonable, and you call it from either the same package or a subclass, then you hit CloneNoSupported.
- if your Pen class implements Clonable, then it should override the clone() method
-  The only way the default Object.clone() gets picked by compiler is when a Cat class implements Clonable but doesn’t override clone(), and you call it from either the same package or a subclass
Clonable is a special marker interface. It could trigger the CloneNotSupported exception, but if you override clone() then this exception may not hit. It’s an obscure detail.
- I think you can override clone() without implementing Clonable, but this is tricky and non-standard.
- You could also implement Clonable without overriding clone() .. see 
https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html (java8) shows two nice tables:
- There’s no more “private protected”
- default access level is better known as “package-private” — strictly more restrictive (more like Private) than Protected (more like Public). The 2nd table shows that
- a “package-private” member of Alpha is accessible by Beta (same package) only, whereas
- a “protected” member of Alpha is accessible by Beta and Alphasub
Not mentioned in the article, but when we say “class Beta can access a member x of Alpha”, it means that the compiler allows you to write, inside Beta methods, code that mentions x. It could be myAlpha.x or it could be Alpha.x for a static member.
Q: When would main() call ..join() vs ..exit()?
I would call ..join() if main thread needs to do something after child threads completes.
I would call ..exit() if main thread has nothing to do and should leave the child threads running.
I now feel an equity swap is an OTC contract; whereas an IBM cash buy/sell is executed on the exchange.
- When a swap trade settles, the client has established a contract with a Dealer. It’s a binding bilateral contract having an expiry, and possibly collateral. You can’t easily transfer the contract.
- When a cash trade settles, the client has ownership of 500 IBM shares. No contract. No counterparty. No expiry. No dealer.
I think a cash trade is like buying a house. Your ownership is registered with the government. You an transfer the ownership easily.
In contrast, if you own a share in coop or a REIT or a real-estate private equity, you have a contract with a company as the counterparty.
Before a dealer accepts you as a swap trading partner, you must be a major company to qualify to be counterparty of a binding contract. A retail investor won’t qualify.