Welcome to NexusFi: the best trading community on the planet, with over 150,000 members Sign Up Now for Free
Genuine reviews from real traders, not fake reviews from stealth vendors
Quality education from leading professional traders
We are a friendly, helpful, and positive community
We do not tolerate rude behavior, trolling, or vendors advertising in posts
We are here to help, just let us know what you need
You'll need to register in order to view the content of the threads and start contributing to our community. It's free for basic access, or support us by becoming an Elite Member -- see if you qualify for a discount below.
-- Big Mike, Site Administrator
(If you already have an account, login at the top of the page)
MFE - maximum favourable excursion from the average entry price. Also the time spent in profit.
I also want to record the realistic start and end times of the opportunity. This will let me determine if I am entering trades too late, or taking profits too early.
The remainder of the entries are a self-evaluation based on a 5-star rating:
Market structure - how well am I identifying trend lines and narrative.
Market conditions - how well am I identifying the current market character and intent.
Profit target - did I have a clearly defined profit target and reason, or did I just FOMO in on the trade without thinking?
Failure identification - did I have a clear failure pattern with a solid plan to abort, or did I go in with the mindset 'this trade is going to work no matter what'.
Strategy selection - did I pick the right strategy and profit/stop targets based on market structure, market conditions, session time remaining?
Focus and clarity - am I in the zone or am I lacking energy or affected by some other negative state?
Risk acceptance - For example, if I'm up on the day, am I worried about losing prior gains? This could cause me to exit trades early or move to breakeven too soon?
Perception of range - Internalisation and awareness of the ATR, and whether the price movement is contracting or expanding (or likely to contract or expand).
Confidence in target - What have I seen that gives me confidence in this trade? Am I taking profit too early?
Entry and Exit execution - the ability to read order flow, time rotations, and press the right buttons at the right time.
Continual risk management - taking a systematic and logical approach to refining stop and profit targets as the trade progresses. Not being blindsided by a bias and over-confidence in the trade, or having invested too much energy into the trade. Sometimes I will let a trade that is nicely in profit turn into a loss as a result of this.
I want to record this information because simply thinking about each helps me. Currently it is a mental checklist, but having it prompted on-screen should help. I want the data entry to be very quick - I'll probably just setup hotkeys 1-5 to record each rating in sequence, so it should take no more than a few seconds. As well as reminding me to consider each of these points, a future plan is to come up with an algorithm for displaying a tilt-o-meter™, plus reminding me to take breaks and keep hydrated, etc.
The next step
I now need figure out how to interface with SierraChart's historical tick data so I can calculate the stats. As I am displaying this information in real time, and I use the same SierraChart instance for live trading, I need to ensure that any longer running calculations do not block SierraChart and yield back within a reasonable time.
Fellow nexusfi.com members have already found a way to access historical trade data, so that is where I'll start.
Getting tick data out of SierraChart and into my own objects
SierraChart presents data in a different format to my own objects. Here are some of the differences:
Different types. For example, SC stores timestamps, price and volume as SCDateTime, float, float. My code uses types Timestamp, Price, Size.
SC stores Price, Volume and Timestamp for each tick in separate arrays. My code uses a single data struct "Trade" to represent each trade, and each struct is stored in a single contiguous collection.
Here is the psuedocode for a Study I wrote that pulls data from a Trade chart and keeps my objects up to date. SierraChart is single threaded and on a rather old Xeon E5-2697 it takes approximately 60 seconds to transfer one month of tick data from SierraChart to my TimeAndSales object. This includes yielding back to SierraChart after a few ms to ensure SierraCHart continues to operate smoothly. Once the backfill has completed, all new trades are propagated in real time.
The reason I want to use my own TimeAndSales object is so I can use multiple threads, pass to my algos for trading, or to my machine learning code for backtesting. The data structures are optimised for the hardware I use and I can offload to the GPU for parallel processing.
For this project, my TImeAndSales object will update each Orderfill and Opportunity (using the Observer Pattern) to generate the statistics I require. This will happen in real time so I can monitor my progress while trading.
I found that a few of the timestamps in the SierraChart arrays are out of sequence. There are two possible reasons for this; either the data sent from the SC historical servers is incorrect, or the time on the local PC has changed while downloading. SierraChart provide an indicator "Out of Order Timestamps Detector" that highlights bars that are out of sequence.
I am writing a custom study that populates my own timeAndSales object. Each time a new bar is received, the study feeds that bar into timeAndSales. timeAndSales then notifies a condition_variable so that my dispatcher can schedule my algos and indicators, which are running on different threads. As my algos and indicators operate in real time and use binary search on historical data for performance, it is necessary that the bars are sent in the correct sequence.
Here is my plan:
SierraChart ASCIL provides a function sc.StartDownloadHistoricalData that will delete and re-download data from a specific point. As my study iterates through each bar, if it detects an out-of-sequence bar, it will call this function to automatically download data from the last in-sequence bar. It will also note the bar for future reference.
If a download doesn't fix the problem, then the problem is with the data on SierraChart's servers and an error will be logged so I can raise a support ticket with SierraChart.
Here is the snippet of code:
OMG, I used a goto!
I tend to write code with the following style objectives:
if statements should contain the exception, not the norm. This means the 'exceptional' execution path is indented (to remind me it is exceptional) and the 'normal' execution path is towards the left margin where it is easier to read.
Separate code blocks into functions where there is good reason to do so, e.g. for code reuse and unit-testing.
If there is no good reason to move code to a function right now, leave the code inline. IMO functions make code harder to read as a) parameters need to be passed, b) it can create code-bloat, and c) the function needs to be defined above the call point which means I need to jump around the page and remember the return point.
Write blocks of code so they can easily be turned into a future function. My method of doing this is to use labels. To avoid compiler warnings on unused labels, I use #pragma warning(disable: 4102).
If a goto statement is easier to read than a state variable and a while loop or if block, prefer the goto.
Example 1:
This is horrible. Normal execution is contained in an if block and indented.
Example 2:
A guard statement is placed at the top of the function. Once the guard statement is passed, it can be forgotten about. This makes for easier reading.
Example 3:
This is the style I used in my code snippet above. My reason for using a goto is similar to using a guard in example 2.
Example 4:
I find example 3 is easier to read and debug. Imagine stepping through the code from top to bottom when slotId == 0. In example 3, I can see exactly where the code branches to and my IDE can take me directly to the label. The label is descriptive so the code is also self-documenting. In example 4, I need to manually hunt for the bottom curly brace. To avoid this, the if block in Example 4 is typically moved to a new function, as in the next example.
Example 5:
If the only reason to introduce the OutOfSequenceCheck function is to make example 4 more readable, IMO it hasn't done that. It has added code-bloat, introduced non-top-to-bottom flow, an undocumented return bool that needs to be tracked, and a timestamp that needs to be passed by non-const ref. In order for code to be self-documenting and avoid non-const refs, OutOfSequenceCheck would need to return a struct comprising bool refreshRequested and Timestamp timestamp. This adds even more code bloat.
I have heard some companies get paid by line of code...
SierraChart calls each custom study every time something happens. E.g. a new trade is received, an order is filled, the mouse is clicked, a drawing is moved, a key is pressed, a related study updates.
The important thing to note is that while the custom study is running, it is blocking SierraChart from doing anything else. Menus will be unresponsive, orders won't process and charts won't update. In some cases, Windows Task Manager will report SierraChart as Not Responding.
Therefore, each study needs to execute very quickly and return control back to SierraChart as soon as possible.
Here are the 2 methods I use to ensure a responsive system:
Yield after a specific time has passed and defer remaining work to the next call.
Put the work onto a queue and have another thread do the work.
For one-off jobs such as loading TimeAndSales data into my own objects, I would generally use method 1. Here is the pseudo code:
This type of design pattern is called a Generator or a Co-Routine.
It is possible SierraChart generates new data faster than my study can process in the allotted time. This results in an ever-growing backlog which is unsuitable for a real-time environment like trading.
To avoid this, most of my algorithms run on separate threads. When SierraChart calls my study, the study simply places the update onto a queue. A dispatcher watches the queue, and distributes the update to each algorithm. Because the algorithms can do the work in parallel and can run continuously, this is much more efficient and there is unlikely to be a backlog due to a sudden high number of trades.
In the case of my journaling software, I have an algorithm to calculate the MAE, MFE, Time spend in profit/loss, and all the other statistics I require for each Session, Opportunity and Orderfill.
The SierraChart Journal study I am writing polls the algorithms and displays their status on the chart.
I'm trying to make trading "more like a video game". The reason is to shift focus away from P&L and towards good trading. I want my dopamine hits to come from good stop discipline, favourable risk/reward, sensible risk management, clear identification of market structure and perfect execution.
SierraChart has UTF-8 support, so I've been looking at emojis as a way to indicate an opportunity outcome.
I was offered some IT contracts when the Covid lockdowns finished. Due to time constraints, I was unable to daytrade or continue development.
I'm now back trading (part time), so will continue development. To get back into trading I've joined Earn2Trade, as it's been almost a year since I day traded. I might start a forum post about that if anybody is interested.