Differences
This shows you the differences between two versions of the page.
desktop:desktop_chart_scripting_overview [2022/01/10 20:20] – rob | desktop:desktop_chart_scripting_overview [2023/09/21 19:58] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 259: | Line 259: | ||
< | < | ||
^ Function ^ Description ^ Example ^ | ^ Function ^ Description ^ Example ^ | ||
- | | PLOT_CENTERLINE | + | | PLOT_CENTERLINE |
- | | PLOT_LIMITLINE | + | | PLOT_LIMITLINE |
- | | PLOT_RANGEMARKERS | + | | PLOT_RANGEMARKERS |
</ | </ | ||
Line 275: | Line 275: | ||
{{: | {{: | ||
+ | |||
+ | ---- | ||
+ | <code lang | Chande Momentum Oscillator> | ||
// Chande Momentum Oscillator | // Chande Momentum Oscillator | ||
// -------------------------- | // -------------------------- | ||
Line 299: | Line 302: | ||
SUMMARY(" | SUMMARY(" | ||
+ | </ | ||
+ | |||
+ | |||
+ | ---- | ||
+ | |||
The summary was specified using the SUMMARY command (the last line of the script). The first value you pass to the summary command is a text value in quotation marks " | The summary was specified using the SUMMARY command (the last line of the script). The first value you pass to the summary command is a text value in quotation marks " | ||
Line 307: | Line 315: | ||
Please continue reading the next section about tick value conversions, | Please continue reading the next section about tick value conversions, | ||
+ | |||
+ | ====== Tick Value Conversions ====== | ||
+ | |||
+ | The script interpreter performs all calculations using market tick values. Tick values are typically different than the values that appear in the DOM or any other window for a given price. It is very ill advised to attempt performing calculations with values that are formatted for display (display values), however there are times where you may want to convert tick values to their cash equivalent, or format a tick value for display so that the numbers displayed make more sense when you are analyzing chart data. | ||
+ | |||
+ | |||
+ | ===== Converting Tick Values to Display Values ===== | ||
+ | |||
+ | Consider the following script: | ||
+ | |||
+ | ---- | ||
+ | |||
+ | <code lang | Example1> | ||
+ | smaval = SMA((OPEN + HIGH + CLOSE) / 3, 10); | ||
+ | plot_line(smaval, | ||
+ | SUMMARY(" | ||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | Here is how it appears on some example charts: | ||
+ | |||
+ | E-Mini S&P 500: | ||
+ | |||
+ | {{: | ||
+ | |||
+ | Corn: | ||
+ | |||
+ | {{: | ||
+ | |||
+ | You will notice for both charts, the summary display for the SMA shows decimal values. These computed values are clearly not valid market prices. | ||
+ | |||
+ | One might try to fix this by removing the decimal points by adding a F0 modifier to the script as follows: | ||
+ | |||
+ | ---- | ||
+ | |||
+ | <code lang | Example2> | ||
+ | smaval = SMA((OPEN + HIGH + CLOSE) / 3, 10); | ||
+ | plot_line(smaval, | ||
+ | SUMMARY(" | ||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | E-Mini S&P 500: | ||
+ | |||
+ | {{: | ||
+ | |||
+ | Corn: | ||
+ | |||
+ | {{: | ||
+ | |||
+ | However as you can see above, this fix is still not correct. 128806 is not a valid price for E-Mini which trades in multiples of 25, and the Corn price still is even further off. | ||
+ | |||
+ | The proper way to fix this display is to tell the script interpreter to convert the tick value to a market display value using the DISPLAY function: | ||
+ | |||
+ | ---- | ||
+ | |||
+ | <code lang | Example3> | ||
+ | smaval = SMA((OPEN + HIGH + CLOSE) / 3, 10); | ||
+ | plot_line(smaval, | ||
+ | SUMMARY(" | ||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | E-Mini S&P 500: | ||
+ | |||
+ | {{: | ||
+ | |||
+ | Corn: | ||
+ | |||
+ | {{: | ||
+ | |||
+ | As you can see above, the SMA values are now show correctly formatted (and rounded) for display. | ||
+ | |||
+ | Please note, you should never attempt to use display-formatted values in your computations. These value are not always suitable for conventional math. Also, attempting to do so will probably result in the script not running to completion. There also is no function to convert a display value back into a tick value. | ||
+ | |||
+ | Because the DISPLAY function is expected to be used extensively, | ||
+ | |||
+ | ---- | ||
+ | |||
+ | <code lang | Example4> | ||
+ | smaval = SMA((OPEN + HIGH + CLOSE) / 3, 10); | ||
+ | plot_line(smaval, | ||
+ | SUMMARY(" | ||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | |||
+ | |||
+ | ===== Converting Tick Values to CASH and Back ===== | ||
+ | |||
+ | Similar to the DISPLAY function, there is a CASH function. The CASH function, converts the tick value to a cash value. The shortcut for this function is $. | ||
+ | |||
+ | To convert a cash value back to ticks use the CASHTICKS function. | ||
+ | |||
+ | ====== The IF Statement ====== | ||
+ | |||
+ | The IF statement allows you to make decisions on the fly in your scripts. It's syntax is a follows: | ||
+ | |||
+ | IF( < test condition >, < true part >, < false part > ) | ||
+ | |||
+ | The test condition is evaluated (for example: CLOSE > OPEN which would be true when the close price of the bar is greater than the open price of the bar). If true, the true part is returned, otherwise the false part is returned. | ||
+ | |||
+ | IF statements are very flexible and can be used to solve a large number of different problems. | ||
+ | |||
+ | Here is an example Money Flow Index script: | ||
+ | |||
+ | ---- | ||
+ | |||
+ | <code lang | example> | ||
+ | // Make the number of periods configurable. | ||
+ | mfperiods = INPUT(" | ||
+ | |||
+ | // Net money flow for this period. | ||
+ | mf = TYP * V; | ||
+ | |||
+ | // Aggregate the net money flow over the user-specified number of periods. | ||
+ | posmf = SUM(IF(TYP > TYP[-1], mf, 0), mfperiods); | ||
+ | negmf = SUM(IF(TYP < TYP[-1], mf, 0), mfperiods); | ||
+ | |||
+ | // Compute the money flow index for this period, taking care not to divide by zero. | ||
+ | mfi = IF( negmf = 0, | ||
+ | IF(posmf = 0, 50, 100), | ||
+ | 100 - 100 / (1 + posmf / negmf)); | ||
+ | |||
+ | // Plot the money flow as a wavecrest centered at 50 with overbought and oversold levels at 80 and 20. | ||
+ | PLOT_WAVECREST(mfi, | ||
+ | SUMMARY(" | ||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | The IF statement was used in a number of different places within this script. It's first use is when we want to add up the positive and negative money flows into two distinct variables. IF(TYP > TYP-1, mf, 0) What this is saying, is if the Typical price is greater than the previous Typical price add the net money flow for this bar, otherwise add zero. Vice versa for the negative money flow: IF(TYP < TYP-1, mf, 0), if the Typical price is smaller than the previous Typical price, add the net money flow for this bar. | ||
+ | |||
+ | The next uses of the IF statement in this script is even more interesting. We nested an IF statement within another IF statement, which perfectly legal syntax. In this case we want to ensure we don't divide by zero (because that would cause our computation to fail). We also want default values based on whether the neg and/or the pos money flow are equal to zero. The logic in computing the mfi variable could be broken down into a table for easier understanding: | ||
+ | |||
+ | ---- | ||
+ | |||
+ | __**Initial Data**__ | ||
+ | < | ||
+ | ^ negmf = 0 ^ posmf = 0 ^ Result ^ | ||
+ | | False| False | 100 - 100 / (1 + posmf / negmf)) | ||
+ | | False | True | 100 - 100 / (1 + posmf / negmf)) | ||
+ | | True | False | 100 | | ||
+ | | True | True | 50 | | ||
+ | </ | ||
+ | |||
+ | |||
+ | ---- | ||
+ | |||
+ | |||
+ | If statements can be used in other places as well. Look at the following example: | ||
+ | |||
+ | ---- | ||
+ | <code lang | Example> | ||
+ | PLOT_HISTOGRAM(VOLUME, | ||
+ | SUMMARY(" | ||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | This produces: | ||
+ | |||
+ | {{: | ||
+ | |||
+ | However, suppose we want to color the bars a different color if the market closes higher than it opened? Here is one way to accomplish that: | ||
+ | |||
+ | ---- | ||
+ | <code lang | example> | ||
+ | PLOT_HISTOGRAM(VOLUME, | ||
+ | SUMMARY(" | ||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | {{: | ||
+ | |||
+ | As you can see, the IF statement is very versatile. Use as needed to make your scripts smarter. | ||
+ | |||
+ | ====== The NIL Field ====== | ||
+ | |||
+ | NIL is a field value similar to OPEN, HIGH, LOW, CLOSE, VOLUME, etc. However, NIL is special in that is represents nothing. You can use NIL to short-circuit computations when certain conditions are met, and more importantly, | ||
+ | |||
+ | |||
+ | ---- | ||
+ | |||
+ | <code lang | Consider a script for Pro-Rated volume:> | ||
+ | prvol = IF(BARPERCENT > 0.05, VOLUME / BARPERCENT, VOLUME[-1]); | ||
+ | |||
+ | // Plot the pro-rated volume bar. | ||
+ | PLOT_HISTOGRAM(IF(INDEX >= COUNT - 1, prvol, NIL), 0.9, COLOR.Yellow); | ||
+ | |||
+ | // Plot the real volume. | ||
+ | PLOT_HISTOGRAM(VOLUME, | ||
+ | |||
+ | // Summary. | ||
+ | SUMMARY(" | ||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | {{: | ||
+ | |||
+ | In this script, we pro-rate the volume for the current bar. We accomplish this using the special BARPERCENT field which returns the percentage of time into the current bar we are. We want to plot the pro-rated volume only for the last bar on the chart, and then we want to overlay a plot of the real volume. | ||
+ | |||
+ | To ensure the first histogram plots only the last bar, we check the current bar INDEX against the total bar COUNT. If not on the last bar, we pass NIL as the value to plot which basically means " | ||
+ | |||
+ | ====== Gotcha 1: Don't Reassign Variables ====== | ||
+ | |||
+ | Once you assign a value or compuation to a variable name. Do not re-assign a different value to that same variable name. The following example illustrates what not to do: | ||
+ | |||
+ | ---- | ||
+ | |||
+ | <code lang | Gotcha example 1> | ||
+ | xval = 10; | ||
+ | xval = xval + 1; | ||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | Though this sort of syntax works in many conventional programming languages, it will result in a script interpreter error and the result will not be as expected. | ||
+ | |||
+ | Remember to think of variables as columns in a spreadsheet. You cannot give a spreadsheet cell more than one formula which is essentially what the above script is attempting to do. | ||
+ | |||
+ | ====== Gotcha 2: Don't Cause Circular References ====== | ||
+ | |||
+ | Similar to variable re-assignment, | ||
+ | |||
+ | ---- | ||
+ | |||
+ | <code lang | Gotcha example 2> | ||
+ | xval = yval; | ||
+ | yval = xval + 1; | ||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | The script interpreter cannot compute xval until it computes yval. It also cannot compute yval until it computes xval. A naive interpreter might get stuck in an endless loop trying to solve these equations, however the script interpreter has a mechanism to detect these situations and report them as errors. | ||
+ | |||
+ | ====== Recursion ====== | ||
+ | |||
+ | There is a special case where you can use circular-like syntax called recursion. Here is an example: | ||
+ | |||
+ | ---- | ||
+ | |||
+ | <code lang | Example> | ||
+ | xval = IF(INDEX = 0, 0, yval[-1]); | ||
+ | yval = xval + 1; | ||
+ | </ | ||
+ | |||
+ | or | ||
+ | |||
+ | <code lang | Example2> | ||
+ | yval = IF(INDEX = 0, 0, yval[-1] + 1); | ||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | In this case, because you using the offset mechanism to refer to a previously calculated value, no circular reference error is generated. However, you must be sure to check the stop condition and assign it a value. In this case our stop condition is the first bar. On the first bar, the previous value of yval would evaulate to NIL and that would short-circuit all following computations to NIL. We used the IF statement to initialize yval on the first bar. | ||
+ | |||
+ | Recursion is considered an extremely advanced topic. It is rarely needed for most indicator calculations. However there are some calculations which are impossible without it (Parabolic SAR is one example). If find find yourself using recursion to solve a computation problem, please feel free to contact support for assistance, further documentation and possibly more examples. | ||
+ |