Welcome

QScript is a very powerful, yet easy to use, computer language designed for building indicators that will work with Wave59. Most traders are not programmers, so this help manual is designed in more of a tutorial fashion to help you learn the concepts as well as describing features. If you simply read through the tutorial included in this help file and review the links in the order suggested below, you should be able to start writing your own studies in a few hours.

Introduction

Script Menu

Plots

Inputs

Variables

Arrays

Loops

Conditional Expressions

Functions

Dots

Color Bars

Trendlines

Text

Regular Expressions

Tutorial

Building Custom Drawing Objects

Debugger

EasyLanguage Converter

System Testing, Optimization, and Automation

Transferring Studies

Complete Glossary of Built-in Functions and Keywords

NOTE: This help file is best viewed with 32bit color enabled. In Windows2000, you can go Start - Settings - Control Panel - Display - Settings to change your color settings. (This path may be slightly different depending on your version of the Windows operating system.)


Script Menu

All script functions are available under the "Script" menu item:

QScript Editor: launches the editor, where you can create and modify your scripts.

Debugger: Launches the debugger, which allows you to step through your script line by line to look for errors and verify correct operation.

View Script Log: Brings up the script log, which holds the output of all print statements and error messages.


Editor

The QScript editor is the main tool you will use to build your QScripts. Most of the functionality can be found under the File menu:

New Script: creates a brand new script

Open Script: opens a saved script

Save Script: saves the current script

Build Script: error checks and compiles the current script into a form that can be executed from the chart. A successfully built script will be available under the "Technical" menu item of a chart, just like any other indicator.

Script Properties: allows you to set the properties for the current script.

Print: prints out a copy of whatever is currently open in the editor.

Export Script(s): allows you to export your scripts for others.

Import Script(s): allows you to import somebody else's scripts for use in your software.

Permanently Delete a Script: allows you to remove old and unused scripts from the software.

Exit Script Editor: closes the editor.

Exit All: closes Wave59.


Debugger

One of the greatest benefits of using a custom interpreted language like QScript is the ability to use an integrated debugger. A debugger is a tool that you can use to step through your QScripts line by line in order to locate errors and verify correct program operation. For some reason, most people seem to be averse to trying out a debugger at first. Don't be! It's very easy to do, and can save you hours of time trying to use print statements to find your error.

In order to debug a script, first apply it to your chart. Odds are you'll get an error message since your script is broken. Don't worry about that. Next, click Scripts - Debugger:

Select the script you wish to debug. You can only debug items marked with "(QScript)". The debugger will appear.

The debugger looks a lot like the editor you built your QScript with, except you can't alter any of the code from here. Once you find the error, you'll have to fix it back in the regular editor . Note that all functions associated with this script are also loaded. You may switch between the main script and the functions by using the tabs at the bottom of the page.

The way the debugger works is first by resetting the QScript to the first bar on the chart and pausing. You can do this at any time by clicking the reset button:

This always stops the script and resets everything to the first bar. Next, you step through the code line by line and pausing after each one. This allows you to actually watch your script as it executes. There are two main ways to advance the script: by stepping (F8), or by tracing (F7).

Both ways increment the current line by one, but tracing moves into functions while stepping does not. So if you don't want to trace through a particular function, press F8 to execute it and stay on the main page. Otherwise, press F7 to switch to the function source and walk through each line of it.

The current line is always highlighted in yellow, so use this as your place marker.

Inspecting Variables

During your debug session, you will frequently need to inspect the value of your variables. The ability to do this is what makes debugging so valuable. To quickly inspect most variables, simply click them once with the mouse. A pop-up box will appear with the current value of the variable.

Alternatively, click View - Local Variables or View - Single Variable Detail.

View - Local Variables will bring up an alphabetical list of all variables in the current script:

If you need more detail on a particular variable, click View - Single Variable Detail:

Use the drop-down box at the top to select the variable you are interested in. The values associated with this variable will be show, along with the variable history. Just like writing a QScript, an offset of 0 is the current value, while an offset of 1 is the value one bar ago.

Break Points

Sometimes it can be tedious to run through a script line by line using F8 or F7. As an alternative to this, you can either use F4, which runs the script until the cursor is hit, or break points.

A break point can be set by clicking on the gutter on the left hand side of the editor. A red dot will appear to signify that a break point has been set. Each time execution reaches this line, the script will be paused for inspection. To remove a break point, simply click the line again to make the dot disappear.

Once break points are set, simply let the script run (F9) and the break points will be triggered automatically. Note that not all lines can be used as break points. You must set your break point at a valid instruction or it will be skipped. So setting break points at blank lines is not a good idea. Remember, if you run through the script to the end due to a bad break point, you can always reset it and try again.


Script Log

The script log is a history of the output of all print statements and error messages generated by all scripts in Wave59. It can be accessed by clicking Script - View Script Log.


Introduction to Scripting

QScript is a computer language that can be used to create your own custom studies. These studies are called "QScripts".

In order to create a QScript, you must launch the Script Editor , type in your code, and Build the script. Once these steps are successfully completed, your script will appear alongside all the other indicators in the "Technical" menu. From a user's perspective, there will be no difference between launching your indicator and one of the build-in non-QScript indicators that shipped with the software.

This help file deals with all aspects of creating, operating, debugging, and transferring custom QScripts. Although it might sound intimidating at first, writing a QScript is actually a very easy thing to do. The language is designed specifically for constructing trading tools, so many advanced operations in other languages only take a few lines in QScript.

The tutorial in this help file will walk you through the creation of some simple QScripts. It is highly recommended that you read through this tutorial before starting to write your own scripts, as it will go a long way to clear up a lot of questions.


Scripting Tutorial

Introduction

This tutorial is designed to teach you how to use the scripting capabilities of this software to construct your own custom indicators. You are encouraged to print this tutorial out and to duplicate all examples on your own machine. If you actually do the examples yourself, you will learn much faster than just by reading what it written.

Each section is broken up into different lessons. You can do them all at once or lesson by lesson. It is up to you what pace to take, but you should complete all lessons in order.

Lesson 1

Getting Started

To begin creating custom scripts, you need to launch the Script Editor . Do this by clicking Scripts - QScript Editor. Then start a new script by clicking File - New Script. The following set up screen will appear:

Name your script "Tutorial" and leave all other settings as they are. A blank page will be created for you.

Your First Script

Now let's jump right into this and create a script:

plot1 = close;

Notice the semi-colon at the end of the line. Each statement must end with a semi-colon. This is how the interpreter will know you are done writing your line of code.

How to Compile

Now let's compile the script. Click File-Build or push F9 to do this. If there are no errors, the editor will give you a "success" message. Otherwise, you will have to fix your errors and try again.

Running your Script

Now go and open a new chart. Load your script onto it. It will be in the Technical menu under "Tutorial". You should see a red line connecting all the closes on the chart. That wasn't hard, was it?

To delete the script, go Format - Indicators, highlight the script, and select "Delete".

Lesson 2

Now let's make a new script:

1 plot1 = close;

2 plot2 = high;

3 plot3 = low;

The red numbers are not actually entered into the Editor. They are only shown here to make it easier to discuss the script. Lines 2 and 3 are the new lines. Notice how each plot statement has a different number.

Compile this and apply it to a chart. You should have three lines now, one along the highs, one along the closes, and one along the lows.

You may reference the following data points in any script:

Open, high, low, close, volume, tick_volume, bid_volume, ask_volume, open_interest, year, month, day, time, and barnumber

Note that scripts are not case sensitive. So there is no difference between "close", "CLOSE", or "CloSe". They all mean the same thing to the interpreter.

Now build this script:

1 plot1 = close;

2 plot2 = high;

3 plot3 = low;

4

5 color1 = red;

6 color2 = blue;

7 color3 = green;

Same script, but we added lines 5-7. Run this script and notice that each line is a different color. Notice that color1 goes with plot1, color2 goes with plot2, etc. Click here for a list of all colors supported by the scripts.

In addition to setting the colors of plots, you can also set line styles and thickness .

We can also reference past values of data:

1 plot1 = (close + close[1] + close[2]) / 3;

2 thickness1 = 2;

On line 1, we add up the closing prices for the last three bars and divide by three to get an average. Close[1] is the close 1 bar ago, and close[2] is the close 2 bars ago. Note that close could also be written as close[0], or the close 0 bars ago (this bar). The interpreter will also recognize "c" as shorthand for close.

Exercises:

1. Write a script that plots an average of the open, high, low, and close prices. The line should be purple and have a thickness of 2.

Lesson 3

This lesson is about variables . A variable is basically a placeholder for a value. Take a look at the following script.

1 myvar = close;

2 plot1 = (myvar + myvar[1] + myvar[2]) / 3;

3 thickness1 = 2;

Functionally, this script is exactly the same as the previous one. But notice that in line 1 we set the close equal to "myvar". Myvar is a variable that we will use to hold the value of the close. We can use almost any name we like for our variables, and we don't have to do anything special before we start using it.

In line 2, our variable "myvar" takes the place of the close. Notice that we can refer to past values of variables in the same way as with price data.

Variables come in very handy when you have a calculation to do with a lot of steps involved:

1 #set up average

2 myvar = open + high + low + close;

3 myvar = myvar / 4;

4

5 #find high - average

6 hidiff = ABS(high - myvar);

7

8 #find average - low

9 lodiff = ABS(myvar - low);

10

11 #plot a band

12 plot1 = myvar + 2*hidiff;

13 plot2 = myvar - 2*lodiff;

Comments

If you ever need to comment your code, use a pound symbol "#". Everything on the line after the pound will be ignored by the script interpreter. The pound symbols are only effective for one line, and will be shown in green on the screen.

Let's step through this line by line:

Line 1: This is a comment line. It will be ignored by the interpreter. Useful to remind us what we are doing when looking at the code later on.

Line 2-3: We take an average of the high, low, open, and close and put it in myvar.

Line 6: The ABS means Absolute Value. It is a built in function , and returns the absolute value of whatever is in between the parentheses. Absolute value makes everything a positive number. In this case we're taking the difference between our average and the high of the bar.

Line 9: We take the difference between the low and the average.

Line 12-13: We make a trading band using our average and the differences found in line 6 and line 9.

Compile yours and see how it works.

Math Operators

Before we go on, this is a good place to discuss mathematical operators. Here is a list:

+ Addition

- Subtraction

* Multiplication

/ Division

^ Exponentiation

Multiplication and division get done before addition and subtraction. This is typical for any programming language, but it can throw you off if you're not careful. Look at the following:

8 + 4 / 2

This could either be:

Add 8 and 4, then divide by 2 to get 6.

or:

Add 8 to the result of 4 divided by 2, which ends up being 10.

See how that's confusing? The computer will actually do things the second way, since division has precedence over addition. Whenever you get into a situation like this, just use parenthesis to specify the correct order. Operations inside the parentheses will be done before operations outside.

So

(8 + 4) / 2

would indeed end up being 6.

You can nest parenthesis too:

( (3 + 3) * (7 - 5) ) / ( 6 / 2 )

This ends up being 4.

Lesson 4

This lesson is about "if" statements. You can control whether something gets executed in your program by using an if or if...else block.

The syntax is:

if (...this is true...)

{

...then do some stuff...

}

Or:

if (...this is true...)

{

...then do this thing...

}

else

{

...do this other thing...

}

To do the testing in the parenthesis, you need some new operators:

Boolean Operators

> Greater than

< Less than

>= Greater than or equal

<= Less than or equal

== Equal

!= Not Equal

These operators always result in being TRUE or FALSE. Here are some examples:

( 3 < 4 ) TRUE. 3 is less than 4.

( 5 > -5 ) TRUE. 5 is greater than -5.

( 5 > 5 ) FALSE. 5 is not greater than 5. It is equal.

( 5 >= 5 ) TRUE. 5 is equal to 5, so the greater than or equal condition is satisfied.

( 2 != 3 ) TRUE. 2 is not equal to 3.

These are simplistic, but you should get the idea. The biggest pitfall you will have is by using "=" instead of "==". The single equal sign is the assignment operator, where you set something equal to be something else. The double equal sign is the equality operator, which tests if two values are the same. In case you're wondering, these operators come straight from C++, so they are very common in the computing world. The compiler should catch any errors you make, and will alert you in the error box at the bottom of the screen.

Here's a real world script example of all of this:

1 if (close>close[4])

2 {

3   plot1=high;

4 }

5 else

6 {

7   plot1=low;

8 }

In line 1, we check to see if the close is greater than the close four days ago. If it is, we go to line 3 and plot the high, otherwise we go to line 7 and plot the close. This is like Gann's trendline indicator.

Note the brackets on lines 2 and 4. Everything in between these brackets will get executed if the statement is true. If the statement was false, everything in between the brackets on lines 6 and 8 would get executed. You can leave the brackets off if you only have one line to execute, but for now make sure to add them in no matter how many lines you've got in your conditional expressions.

We could have done this a different way using two separate if statements:

1 if (close>close[4])

2 {

3   plot1=high;

4 }

5

6 if (close<=close[4])

7   plot1=low;

Lines 1-3 plots the high if the close is greater than the close 4 days ago, and lines 6-7 handle the case when it's not. Notice that we left the brackets off of the second if statement. We can do this because we only have one line to execute in our true clause.

This is pretty straight forward. It works just like English.

You can link together a number of conditional expressions using the and and or operators. The and operator returns true if both arguments on either side of it are also true, false otherwise. The or operator returns true if one of the arguments on either side of it is true, false only if both are false. They work just as they sound in English.

Here's an example:

1 if ((close>close[4]) and (close > open))

2 {

3   plot1=high;

4 }

In this case, we only plot the high if the close is greater than the close of 4 bars ago, and the current bar has a close greater than the open. If either one of these conditions is not met, the program will not execute the marked block.

Using or:

1 if ((close>close[4]) or (close > open))

2 {

3   plot1=high;

   4 }

This is the same code as the last example except we are using an or instead of an and. In this case we will enter the marked block if the close is greater than the close 4 bars ago, or if the close of the current bar is greater than the open. Only one of these conditions needs to be true for us to enter the block. The only way we won't enter the block is if both conditions evaluate to false.

Exercises:

1. Create an indicator that plots the average of the open, high, low and close. When this average is greater than yesterday's average, make the plot blue. When the average is less than yesterday's make the plot red. You will need to use variables and if statements to make this work.

Lesson 5

This lesson we look at loops. A loop is just a portion of code that gets repeated a number of times. There are two kinds of loops in this language, the for loop and the while loop.

For Loops

The syntax here is:

for (variable = start_value to end_value by increment_value)

{

...do this stuff...

}

A for loop needs to use a variable as a counter. In the example above this variable is aptly named "variable". When we enter the loop, the variable will be set equal to start_value. Each time we pass through the loop, the variable will be incremented by increment_value. The loop stops when the variable passes end_value.

1 for (ctr=0 to 10 by 1)

2 {

3   myvar=myvar+1;

   4  }

When we first hit line 1, "ctr" will be set to 0. Then we will move down the loop to line 4. Our "ctr" variable will be incremented by 1 (so now it's equal to 1), and we will jump back to line 1. Then we do the loop again. This keeps up until ctr is equal to 10, in which case we break out of the loop and go to line 4. Note that the final loop is executed with a value of 10.

We can also do this by counting down rather than up:

1 for (ctr=10 to 0 by -1)

2 {

3   myvar=myvar+1;

   4  }

In this case we start the loop with "ctr" equal to 10. Then we keep subtracting one until "ctr" is 0, when we break out. Notice at our increment value ("by -1") is a negative number, which is actually what makes us go down rather than up.

Note that you don't have to tab line 3 in, but it just makes things cleaner and easier to read.

Let's take a look at a script:

1 avg=0;

2

3 for (ctr=0 to 9 by 1)

4 {

5   avg=avg+close[ctr];

6 }

7

8 avg=avg/10;

9

10 plot1=avg;

This script computes a moving average of the closes, adding up the last 10 closes, dividing by 10, and plotting the result.

Line 1: Set the variable "avg" equal to 0 before we enter the loop. We will use this variable to hold our average.

Line 3-6: This is the heart of the script. The loop starts at 0 and finishes at 9, so we go 10 times around. Each time the loop executes, we increment avg by the close "ctr" bars ago. Notice two things. First, a variable can be set to itself plus something else. This is how we add new values on to it. Second, notice that we are using our "ctr" variable to decide which close to add on to "avg". Since "ctr" moves from 0 to 9, we add up all the closes from 0 to 9 bars ago.

Line 8: We need to divide the total by 10 to get a real average. Again, note that we can assign a variable to itself.

Line 10: Finally, plot the result.

Run this script and verify that it does plot an average.

While Loops

The second kind of loop available in our scripts is the while loop. The syntax is:

while (...this is true...)

{

...do this stuff...

}

Here's a more realistic example:

1 while (ctr<10)

2 {

3   myvar=myvar+1;

4   ctr=ctr+1;

   5  }

Note that we are explicitly incrementing our "ctr" value in line 4. This is because the while loop only checks to see if ctr is less than 10. It doesn't increment anything by itself.

This means you can write infinite loops that never end if you're not careful! Pay attention to this, because you can lock the software up if you forget! Here's a bad example:

BAD EXAMPLE: Don't enter this unless you want to lock up the software!

1 ctr=0;

2 while (ctr<10)

3 {

4   myvar=myvar+1;

   5  }

Let's step through this. Line 1 sets ctr equal to 0. Line 2 begins the loop. Ctr is less than 10, so the statement is true. Move to 4. Add 1 to myvar. Then we fall to 5 and bounce back up to 2. Ctr is still zero, so we continue the loop. Since ctr will never change, the loop will never end!

So you need to be very careful about your ending condition. This usually means you will have to increment something within the loop itself.

Here's our moving average done with a while loop:

1 avg=0;

2 ctr=0;

3

4 while (ctr<10)

5 {

6   avg=avg+close[ctr];

7   ctr=ctr+1;

8 }

9

10 avg=avg/10;

11

12 plot1=avg;

Line 1-2: Set our variables equal to 0 before we enter the loop. Notice that we have to track ctr by ourselves when using a while loop.

Line 4-8: Run the loop. Each loop we add a close to avg, and add one to ctr. Eventually ctr will be greater than or equal to 10, so we are assured that our loop will exit.

Line 10: Divide avg by 10 to get final result.

Line 12: Plot it.

Run this script and verify that it works.

Exercises:

1. Calculate and plot three averages using the same script. Do a 4, 9, and 18 bar average of the close. Make each one a different color and make the 18 bar average thicker than the others.

Lesson 6

Once you start building your own scripts, you will realize the need to be able to change various parameters from within charting, rather than having to go back an rebuild your scripts. This can be done by declaring inputs.

An input is like a variable that gets set by the user. Declare an input like this:

input: length(10);

The "input:" directive says we are declaring an input. "Length" is the name of our input, and it is initially set to 10. We will be able to alter this value the same way as we change the parameters in the built in indicators.

Inputs are treated just like variables except they get set outside the main program. You can set them to numbers or functions .

Let's make it so we can adjust the length of our moving average calculated in the last lesson:

1 input: length(10);

2  avg=0;

3

4 for (ctr=0 to length-1 by 1)

5 {

6   avg=avg+close[ctr];

7 }

8

9 avg=avg/length;

10

11 plot1=avg;

Line 1: We add our input here. Initially the input is set to 10, but we can change it in charting if we desire.

Line 4: Notice that we now go up to length-1 in our loop. Since we start at 0, we need to go one less than length to get the full count.

Line 9: Now we are dividing by length instead of 10.

Run this script and verify that it works.

Exercises:

1. Momentum is calculated by subtracting a past close from today's close (ex: close-close[10]). Build a script that calculates a momentum curve based on an input value. Plot the 3 bar average of this curve and the zero line so we can tell if momentum is positive or negative. Note: you will have to set plot type to "Screen" for this exercise.

Lesson 7

You're basically an expert now if you understand everything that came before this lesson. There's really not much more to learn. All that is left is some practice to get things under your belt and you should be off and running. This lesson is to mention a few things that were ignored in the previous lessons.

Nesting

You can nest multiple if statements and loops. The interpreter can track each loop separately.

So:

if (a<b)

if (c<b)

plot1=a;

else

plot1=b;

else

plot1=c;

...is a totally legal thing to do. Loops are the same way. Note that tabbing your code gets to be very important when doing nested if...end statements. That's because you can easily get lost in the code if you get sloppy about the tabbing. The same goes for brackets. The code above doesn't use them since all true/false clauses were only one line, but they would be very helpful in preventing errors as well as giving visual clues as to which block each particular statement belongs.

Arrays

Arrays are a useful data structure that is available to you in your scripts. You will not use them often, but when you need them they are invaluable. Click here for more about arrays.

Functions

All modern programming is based on functions. You don't need these for simple scripts, but you'll use them some day for sure if you keep writing your own indicators. Click here for the custom function page. Click here for a list of built-in functions.

Regular Expressions

Pattern matching is a common task when programming trading indicators, and you'll likely do quite a bit of it. When the time comes to write really complicated patterns, consider using QScript's powerful regular expression functions instead. Regular expressions can be confusing to learn at first, but they are incredibly powerful when it comes to searching for patterns.

Drawing Objects

QScripts can be used to construct drawing objects as well as indicators. Fibonacci retracement levels, trendlines, and other tools can be created with QScript.


New Script

To create a new script, open up the editor and select File - New Script. The following set up screen will appear:

You need to enter the appropriate information for the script you wish to build. Note that this information can be changed later by clicking File - Script Properties .

Name: This is the name of your QScript. No spaces or punctuation characters are allowed in the name. This name will appear in the indicator list to identify your script once everything has been built .

Type: Select either Indicator or Function for the type of script you wish to create.

Reference Bars: This is the number of bars of history the script interpreter will store for your script. You will not be able to access a variable's history farther back than this setting, so make sure it is greater than any offset you use in your script.

Scaling: Select Price or Screen. Price scaling plots your indicator using the same price scale as the data on the chart. This is appropriate for moving averages, etc. Screen scaling plots your indicator according to its own scale. This is appropriate for oscillators such as momentum or RSI.

Hotspots: Sets the number of screen hotspots to collect when the script is loaded. These hotspots allow a script to act just like a regular drawing object. Click here for more information.

Update Style: Select whether you wish your script to update every time a new tick arrives from the data feed, or only at the close of the bar. Updating every tick can be potentially very CPU intensive on complicated scripts (especially in fast markets), so keep that in mind when choosing an update style.


Script Properties

By clicking File - Script Properties, a set up form will appear allowing you to change all the important properties of your QScript. This form is functionally identical to the one that appears at the time of creating a new script .


Build Script

Once you have completed entering the code for your QScript, you are ready to Build it. Click File - Build to do this.

Building a script converts the English-like statements into a form more easily read by the computer consisting primarily of operation codes and data values. The new format can be executed extremely quickly by the interpreter.

During the build phase, the software will error check your code and inform you of any problems it encountered. Errors will appear in the error box at the bottom of the editor:

You can double-click any error with a line number after it to be taken directly to the offending line in the script. The error occurs somewhere very near this spot - usually on the same line but sometimes on the one directly above in extended statements.

A successfully compiled script will return "Script Compiled Successfully!" in the error box.

Important: Sometimes you may receive warning messages in the error box. Although warnings do not abort the compilation of your script, they do point out potential problems that the compiler feels you should be aware of. Make sure to investigate all warnings!


Export Script(s)

You can export any scripts you write in order to give them to your friends or clients. To export your scripts, start the QScript Editor and click File - Export Script(s). That will bring up the following page:

Select the indicators and functions you wish to transfer by highlighting them in the left-hand list, and clicking the "Add" button. You may transfer as many studies as you wish in a particular archive. When done, click "OK" to move on.

If your studies use other functions in their calculation, you will be asked if you wish to include them in your exported archive or not.

The next window that will appear lets you select what kind of archive you wish to create:

You have three choices: Open, Protected, and Secure. The graphic above describes each one in more detail.

Protected and Secure modes use modern cryptography to protect your ideas from being stolen by others. If you are a software vendor and are trying to sell your trading tools, you really don't need the headaches created by finding your cracked indicators posted for free on news groups or websites. Unless you really do mean to give your ideas away, consider exporting using Protected or Secure modes.

If you choose to export a script using Secure mode, you'll need the recipients customer number. This can be found by clicking Help - About from within the software. Each person has their own unique customer number, so this is a way to protect your studies from being copied once you have sent them off.

Once you've selected the type of archive file to create, you'll be asked where to save it. The default location is the /export folder in Wave59's main program directory.


Import Script(s)

Importing scripts from an archive file is extremely easy. Simply double click the archive and a special program will be launched to do this for you. Alternatively, you can launch this program from within the QScript Editor by clicking File - Import Script(s). A window similar to the following will appear:

This lists all the scripts contained in the archive. Functions are denoted by a trailing "(F)". If there is a function you do not wish to transfer, highlight it and click "Remove". If you accidentally remove a study and you didn't mean to, click "Restore" to start over. When you're done, click "OK".

And that's it. All functions will be transferred over and will be immediately available for use within charting.


Indicator

There are two kinds of QScripts: indicators and functions. Indicators are scripts that can be loaded into a chart and plotted. Functions are actually helper scripts designed to make it easier to write indicators.


Variables

Variables in QScript are simply place holders for other values. They come in very useful because they allow you to refer to a value with a word rather than a number. They also speed up execution of the script since the value in the variable can be calculated once, then used many times afterwards.

In QScript, unlike most other languages, there is no need to declare your variable before using it. Simply come up with a name and start using it as in the following example:

pi = 3.14;

This assigns the value 3.14 to "pi", which can be called by the program later on. Note that variable names are not case sensitive, so pi, PI, and Pi are all the same thing.

We can use this variable just as if it were a number:

2*pi is the same as 6.28

pi / 3.14 is the same as 1

Another benefit of using variables is that since the interpreter saves variable history, you can access old variables. This is done in the following way:

pi[1] - returns the value of pi one bar ago

pi[5] - returns the value of pi five bars ago

This is useful in calculating averages, etc. Note that pi[0] is the same as pi - both refer to the bar that is currently being examined. Since the interpreter evaluates scripts on every bar, starting from the oldest and working toward the newest, each bar will be the 0 offset at one time or another.

Important Tip: Since variables do not need to be declared, you can get into trouble with spelling errors. So if you accidentally typed "Pii" when trying to refer to "Pi", the compiler would not flag this as an error but would just assume you are trying to use a different variable. This can cause your indicator to perform unexpectedly, as you are using different variables for different things. Usually the compiler will generate a warning when it finds variables that never get assigned values, as these are usually misspellings.

Rather than checking each variable to make sure it is spelled correctly, simply click View - User Variable list after you build your script. This will bring up a list of all variables used in your script:

Now a simple inspection of this variable list will tell us something is fishy about "Pii" and "Pi".


Comments

Comments are notes that you can write along side your code to explain a particular expression or procedure. Comments begin with a "#" and continue to the end of the line. The compiler will ignore all comments, so you can write anything you like in a comment without it affecting your script. Below is an example:

a = 34; # set a equal to 34

In the line above, variable "a" is set to 34, but everything after and including the # is ignored. Since comments are color-coded, it's easy to see what will be ignored by the compiler.


Boolean Operators

These operators can be used inside any expression that returns true or false. There are five of them, and they follow the conventions maintained in C++:

== Equality operator. Tests for equality of two quantities. 2 == 2 returns true, but 2 == 3 returns false. Remember this operator as it's a stumbling block at first. A single equals sign assigns a value - two equal signs test for equality!

< Less than operator. Returns true if the quantity on the left is less than the quantity on the right. False otherwise. 2 < 3 returns true, but 3 < 2 returns false.

<= Less than or equals operator. Returns true if the quantity on the left is less than or equal to the quantity on the right. 2 <= 3 returns true, 2 <= 2 returns true, but 3 <= 2 returns false.

> Greater than operator. Returns true if the quantity on the left is greater than the quantity on the right. False otherwise. 10 > 1 returns true. 1 > 10 returns false, as does 10 > 10.

>= Greater than or equals operator. Returns true if the quantity on the left is greater than or equal to the quantity on the right. 10 >= 1 returns true, as does 10 >= 10. 1 >= 10 returns false.

!= Inequality operator. Returns true if the two quantities are not equal to each other. Returns false if the two quantities are equal. 2 != 3 returns true, but 2 != 2 returns false.

And operator. Returns true if the two quantities on either side are also true. (2<3) and (1<4) would evaluate to true, but (1==4) and (3<123) would be false since the first argument is false.

Or operator. Returns true if either of the two quantities on either side is also true. Returns false only if both quantities are false. (2<3) or (9>1) returns true since both are true. (2<3) or (1<-78) returns true since the first argument is true. (0>123) or (0>56) returns false since both arguments are false.


Loops

You can use loop structures in order to execute a particular code block a given number of times. There are two loop constructs in QScript:

For Loops:

This uses a counter to determine how many times the loop executes.

for (ctr = 1 to 10 by 1)

{

...code block...

}

You initialize the counter ("ctr" in the example above) to a number to start the loop. Each time the loop is executed, the counter variable is incremented by a given amount ("by 1" in the example above). This continues until the counter is equal to the stopping value ("to 10" in the example), at which time the program exits the loop. Note that the stopping value is run before exiting.

While Loops:

A while loop uses a true/false test to determine whether or not to keep looping.

while (true/false statement)

{

...code block...

}

As long as the condition in the parenthesis after the while loop is true, the while loop will continue executing. When it is false, the loop will exit.

For more information about loops, along with example code, please see the lesson 5 in the tutorial .


Conditional Expressions

A conditional expression is used to selectively execute different blocks of code depending on whether test conditions are true or false. This is done using the if construct.

For example:

if (a > b)

{

...code block...

}

The code block between the brackets will only be executed if a is greater than b. If not, the entire block will be skipped.

Else statements can be used to provide code for when the statement is false.

if ( (a > b) and (a > 0) )

{

...code block 1...

}

else

{

...code block 2...

}

In this case, code block 1 is executed if a is greater than b and also greater than 0. Otherwise, code block 2 is executed.

If...else statements can be nested to provide many different paths of execution:

if (a > b)

{

...block 1...

}

else if (b > c)

{

...block 2...

}

else

{

...block 3...

}

If a is greater than b we execute block 1. If not, we check if b is greater than c. If it is, we execute block 2. If it isn't, we execute block 3. Note that the final else block goes with if (b>c), which means that only one block will be executed at any time.

For more information, including example code, please review lesson 4 in the tutorial .


Plots

Plot statements are way QScripts draw values on a chart. They are treated like special variables, and must follow the naming format of "plot" + number.

For example, if we wanted to plot the close, we would write the following:

plot1 = close;

That statement simply assigns the value of the close to plot1, which the interpreter knows is a special variable and should be plotted.

There is no limit to how many plot statements can be contained in one QScript, so the following is perfectly legal:

plot1 = close;

plot2 = open;

plot3 = high;

plot4 = low;

plot5 = close[1];

plot6 = open[1];

etc...

The plot statements do not need to follow any particular numbering strategy either. In other words, plot1 does not need to come before plot2.

Modifiers

Each plot statement can have a number of modifiers. These modifiers govern the color, thickness, and style of the plot statements.

Color modifiers

To change the color of a plot statement, simply use a statement like the following:

plot1 = close;

color1 = blue;

Color1 modifies plot1, and in this case sets it to blue. Click here for the complete color list.

Thickness modifiers

To change the line thickness of a plot statement, simply use the thickness modifier:

plot1 = close;

thickness1 = 3;

This makes the thickness of plot1 equal to 3 pixels. Normal line thickness is 1 for reference purposes. There is no maximum thickness level, although practically things start to look strange past about 5 or 6.

Style modifiers

The last modifier is the style modifier, which changes the type of line drawn. There are 7 style types that can be used. Note that many of these styles require a line thickness of 1.

plot1 = close;

style1 = ps_dot;

This code turns plot1 into a dotted line.


Color List

The following colors are available in QScript:

Red

Blue

Green

Black

White

Yellow

Fuchsia

Silver

Navy

Purple

Lime

Olive

Gray

Maroon

Teal

Aqua


Style Types

The following line styles are available in QScript. The "PS" at the front of the constants stands for "Pen Style".

ps_Solid: regular solid line

ps_Dot: dotted line (requires thickness of 1)

ps_Dash: dashed line (requires thickness of 1)

ps_DashDot: dash - dot alternating line (requires thickness of 1)

ps_DashDotDot: dash - dot - dot alternating line (requires thickness of 1)

ps_Clear: invisible line

ps_Histogram: histogram


Inputs

Inputs are variables that can be set outside of the script itself. This is useful because that way you can change a particular setting and the whole script won't have to be re-compiled. The other benefit is multiple instances of an indicator can be applied to a chart with different settings. For example a 10 bar and 20 bar moving average could be added to the chart using one QScript with an input setting for the length parameter. Input values can be set by clicking Format - Analysis Techniques from the chart, so it's very easy to change them.

To include an input in your QScript, simply declare it using the "input:" declaration.

input: price(close), length(10);

The above statement declares two inputs, "price" and "length". Once they have been declared, use them the same way as any other variable:

avg = average(price,length);

plot1 = avg;

plot2 = price;

Note that the input statement above contains the default parameters "close" and "10". You'll need to supply these if your QScript is an indicator . If it's a function , leave off the default parameters.


Formatting QScripts

Once a script has been applied to the chart, you may wish to change it's parameters. This is done in the same way as any other indicator - by clicking Format - Analysis Techniques from the chart. When you select your indicator, a window similar to the following will appear:

The input name is on the left, and the current setting is on the right. To change a setting, simply click the appropriate cell and enter the new value.

If you execute a right mouse click, you'll bring up the common settings pop-up menu:

This will allow you to enter common inputs (such as colors) quickly and without typing errors.

Once you have changed the inputs to their new values, click "OK" to close out the form, and the indicator will be recalculated using the new parameters.


Arrays

Arrays are like variables except that one array refers to an entire index of values. Think of an array as a file cabinet with many folders. Folder "0", at the front of the drawer, contains one value. The next folder back, Folder #1, contains a new value. All of these folders belong to the array, and the individual values in the array can be accessed using the folder index. Arrays work like this:

Our array is called "MyArray", but it actually references 5 different values, shown in red. If we wanted to get the value located at index 2, we would write "MyArray[2]". If this were QScript, that would be equivalent to writing the number 9, since that's what is stored at index2.

In order to use an array in QScript, you must first declare it with a "define" statement:

define ARRAY myarray[];

This tells the compiler that "myarray" is an array and not a variable, which it would otherwise assume. The "ARRAY" modifier doesn't have to be capitalized, but it's good form to do it that way.

Once you've got an array, you can just start inserting values:

myarray[2] = 5;

myarray[17] = 9;

etc...

Note that you can enter values in any order you like. In the example above, we skipped indexes 0-1 and 3-16. Empty indexes are assumed to have a value of 0.

Here are some important points to remember about arrays in QScript:

1) The first item in an array is at index "0". This is a little confusing at first, but is the same in nearly every programming language. This means that the last element will be at the index value one less than the total number of elements in the array. So in the picture above, we have 5 elements, but the last one is at index 4.

2) Arrays never change their values from bar to bar like variables. MyArray[0] in the above example will be 0.56 until you explicitly go in there and change it.

3) QScript arrays use dynamic memory allocation, so they shrink and grow according to what you tell them to hold. This means that you never have to set a size for an array, and you can put as many items in an array as the memory in your computer permits.

4) Negative indexes to an array are used to access data from the end of the array (the right side in the picture above). So MyArray[-1] is 57, and MyArray[-3] is 9. Notice that -1 is the index for the last element because -0 is the same as 0, which is the first element. MyArray[-6] will result in an error in this example.

Specialized Array Functions

There are a number of built-in functions designed to be used to manipulate arrays. You probably won't use them very often, but they really come in handy when you need them. Just tuck this information away and be aware that these functions exist.

Push(array, value)

This pushes a value on to the end of an array. It's like inserting a file folder at the back of the drawer. If we had an empty array "testarray", we could do the following:

push(testarray, 3); # testarray contains {3}

push(testarray, 8); # testarray contains {3, 8}

push(testarray,12); # testarray contains {3, 8, 12}

Pop(array)

This is the opposite of Push. It takes the value at the end of the array, removes it permanently from the array, and returns it.

Given the array "testarray", where testarray = {2, 4, 5} we could do the following:

myvar = pop(testarray); # myvar contains 5, and testarray contains {2, 4}

Shift(array)

Shift works exactly like Pop, except the value is taken from the front of the array rather than the end.

Given the array "testarray", where testarray = {2, 4, 5} we could do the following:

myvar = shift(testarray); # myvar contains 2, and testarray contains {4, 5}

UnShift(array, value)

UnShift works like push, except the value is inserted at the very front of the array rather than the back.

Given the empty array "testarray":

unshift(testarray, 3); # testarray contains {3}

unshift(testarray, 8); # testarray contains {8, 3}

unshift(testarray,12); # testarray contains {12, 8, 3}

Sort(array)

Sort orders the array according to value (or alphabetically if the array is made up of strings ). The array is sorted with the smallest values at the front and the largest at the back.

For example, if we have the array "testarray" with values {3, 5, 1, 2}, we could do the following:

sort(testarray); # the elements are now {1, 2, 3, 5}

If you want to sort an array with values going largest to smallest, simply call sort, then reverse (the next function).

Reverse(array)

Reverse reorders the array so that the front items go to the back and the back items go to the front. It works just as you would expect.

Given "testarray" with values {1, 2, 3, 4, 5}:

reverse(testarray); # the elements are now {5, 4, 3, 2, 1}

Length(array)

This function returns the number of items in the array.

Given "testarray" with values {5, 6, 7}:

myvar = length(testarray); # myvar equals 3 after this call

This function is very useful for iterating over an array in a loop. For example:

# this resets all array values to 1

for (i = 0 to length(testarray) - 1 by 1)

testarray[i] = 1;

Remove(array, index)

This removes the element at the given index from the array. The value of the element is not returned.

Given "testarray" with values {1, 2, 3, 4, 5}:

remove(testarray, 2); # the array now contains {1, 2, 4, 5}

Clear(array)

This deletes all elements from the array.

Given "testarray" with values {1, 2, 3}:

clear(testarray); # the array is now empty

Multi-Dimensional Arrays

QScript also supports multi-dimensional arrays. This kind of array has more than one index. A two dimensional array looks something like this:

To access a value from a multi-dimensional array, you need to supply index values for each dimension. In the array above, MyArray[1][1] is equal to 3.14.

The example above demonstrated a two dimensional array as a grid. A three dimensional array would look like a cube. I'm not sure what a four dimensional array would look like (a row of cubes?), but that doesn't stop you from using one. There is no limit to how many dimensions you can have in an array besides the memory in your computer.

Declaring a multi-dimensional array is similar to declaring a regular array, except you must provide the lengths for each dimension. If we wanted a 3x4x2 array, we would do it like this:

define ARRAY myarray[3][4][2];

Note that the numbers used in the declaration refer to the size of the array, not the largest index numbers. In a 3x4x2 array, the largest index is actually [2][3][1], so be careful. Multi-dimensional arrays are still 0 based! If you try to write to an index outside of the defined range, you'll get an error.

Now we can go ahead and use our array. Note that none of the specialized array functions discussed above will work with multi-dimensional arrays. Also note that multi-dimensional arrays are static in nature. This means you can't just add values to them. They maintain the dimensions they were declared with, and trying to read or write values to indexes outside of this range will result in an error.


Data Types

Unlike most other programming languages, QScript does not have data types. Variables can hold strings, numbers, true/false values, and references. The interpreter automatically handles conversions and type tracking, which makes programming much simpler.

Don't bother reading any more if that's all you wanted to know. The rest of this page is supplemental information for those interested. You don't need to know any of this to successfully write your own studies in QScript.

In the background, a QScript variable will be one of following C data types:

  • Double precision floating point numbers (3.14159..., etc)
  • Integer numbers (-2,-1,0,1,2,3, etc.)
  • Boolean values (true / false)
  • Strings ("hi", "blargh!")
  • References (pointers to other variables)

It is actually difficult to tell what kind of data a variable holds because the interpreter can convert one type to another on the fly as it chooses. But given the nature of trading indicators, most variables end up as doubles in the end.

If you want to force the interpreter to convert a variable to a given type, you can do so with the following functions:

to_Int(X) : Converts X to an integer.

to_Double(X) : Converts X to a Double.

to_String(X) : Converts X to a string.

These functions come in handy when writing DLLs . Aside from that, you should never have to use them.


External DLLs

QScript can use DLLs written in C or C++. You'll need the header file found in .../scripts/DLLs. Also check out .../scripts/DLLs/demo for a demonstration DLL. Below is a copy of the information found at the top of the header file.

OVERVIEW:

Any custom DLLs you create for Wave59 will require this file.

The prototype for your function needs to be similar to the following:

extern "C" (int/double/string/void) __declspec(dllexport)

myfunc(WAVE59_DATASTRUCT *price_ptr, int currentptr,int *int_args,

int num_int_args,double *double_args, int num_double_args,

char **string_args,int num_string_args);

WHAT THE PARAMETERS MEAN:

price_ptr: a pointer to the internal data structure for the price chart (see below)

currentptr: the index value of price_ptr array for the current bar. So

price_ptr[currentptr] is the data for the current bar, and

price_ptr[currentptr-1] is for the bar right before this one.

int_args: pointer to an array of ints that holds all int values passed in from

the QScript call.

num_int_args: how many values are in int_args.

double_args: same as int_args but for double parameters.

num_double_args: how many double args in double_args array.

string_args: same as int_args but for string parameters.

num_string_args: how many string args in string_args array.

WHAT YOUR FUNCTION SHOULD RETURN:

Your function can return an int, double, null-terminated array of chars,

or void. The return type is specified in the QScript declaration, so make

sure to be consistent with your return types or you'll get unexpected

results.

WHERE TO PUT YOUR DLL:

All DLLs are accessed dynamically as they are called, so you've got to

make sure that you put your DLL in the right place before you try and

use it from QScript. The folder where Wave59 will look for DLLs is

\scripts\dlls. This is the same location you should have found this

header file, so you probably already know how to get there.

The application directory of Wave59 can be found at the following

registry entry:

HKEY_CURRENT_USER\Software\Wave59_Install\Dir

So if you are building an automatic installation program, get the directory

from there and add a \scripts\dlls to the end of it to locate the folder

where you need to place your DLL.

HOW TO CALL YOUR DLL FROM WAVE59:

Once you've properly installed your DLL, calling it is very simple. If we

have a function "myfunc" in our DLL "SomeDll", we could execute this function

from QScript as follows:

define dll int, SomeDll, myfunc, myfunc;

...

a=myfunc();

The format for the define at the top is return type, dll name, function name,

and qscript alias. Don't put any paths in the dll name. The qscript alias is

the function's name as used in the script. Note that this can be different

from the true name as registered in the DLL.

The return types that QScript will recognize are int, double, string,

and void. String refers to a plain old null-terminated array of chars.

You only need to define a function once in each script that the function

appears in, but you'll need to do a separate declaration every function in

your DLL that you plan to import. Also, note that DLL functions replace any

other functions of the same name, so you have the ability to overload any

built-in function with your own version if you have some reason to do so.

TIP: Some compilers append an underscore (_) to exported functions. So if

Wave59 can't seem to find your function, you might consider this possibility.

In the example above, you would need to write...

define dll int, SomeDll, _myfunc, myfunc;

...

a=myfunc();

...instead. Note that the QScript call is the same - only the function name

in the declaration changed. That's because the alias is still "myfunc".

Alternatively, you should be able to fix the problem by adjusting the

settings in your compiler to avoid this behavior.

TIP 2: If you are giving your DLL to another user (or are selling it), you

probably ought to put it in its own QScript function wrapper to make it

easier on your users. Most people would rather not have to go through the

routine of defining the DLL at the top of the script, so keep things user

friendly when you can! By wrapping DLL calls inside their own QScript

functions, you'll also avoid errors due to misspelling the DLL name and

declaring the wrong return type.

MORE DETAILS (if you are still confused!)

QScript was designed to be a typeless programming language. A variable can

take on the values of a string, integer, or double at any time without any

complaints from the interpreter. In fact, the data for a variable is hardly

ever the same type it was when the script first began running, so it's very

hard to tell what C type a particular variable is at a given moment in

the execution of a script.

Because of this, QScript will take all parameters you supply it with and

break them into three groups when a DLL is called. All the integers go into

one array, all the doubles into another, and all the strings into a third.

The order between parameters of the same type is always preserved, but the

overall order is not since the arguments get split up in this way.

In order to keep you from having to guess which array your parameter landed in,

you can use the three QScript functions below to explicitly cast values right

before you pass them to the DLL.

To_Int

To_Double

To_String

So rather than writing this (in QScript)...

define dll double, MYDLL, my_dll_function, my_alias;

...

a = 1; b = 2.5;

result = my_alias(a,b);

..write this instead:

define dll double, MYDLL, my_dll_function, my_alias;

...

a = 1; b = 2.5;

result = my_alias(to_double(a),to_double(b));

That way you have control over where your variables will appear in the

arrays passed to your DLL.

Note that if you pass a qscript array into the dll function call, all of

it's values will end up in the appropriate array for the DLL just as if

you had entered them one-by-one, starting with the value in the lowest index.

This is a good way of passing a large chunk of indicator history to a custom DLL.

The arrays that hold the variables are temporary, so you can go ahead

and change their values without having to worry that it will affect the

corresponding variables in the QScript implementation. Just don't delete

them!

IMPORTANT NOTE: the price_ptr structure is not a copy - it's the actual

data structure used by Wave59 for the current chart. So don't ever change

any of its values unless you really mean to alter the data in some way.


Strings

A string in QScript is simply a bunch of characters surrounded by quotation marks. For example:

"Hi there."

"3+2"

"Buy on a cross over this line!"

All of those were strings because they were surrounded by quotation marks. The interpreter will never change anything around inside one of your strings, so you can write anything you wish inside them without affecting the calculations in your program.

Strings are useful because they can be printed to the script log or printed to the screen using some of the built-in text functions.

Helpful note:

If you want to print a quotation mark inside your string, do so by using two quotation marks in a row.

So the statement:

print "He said ""hi!"" to me.";

...looks like this in the script log:

He said "hi!" to me.


EasyLanguage Converter

QScript has the ability to convert TradeStation EasyLanguage code over to QScript. Simply copy the EasyLanguage source code, paste it into the QScript Editor , and click Convert - EasyLanguage to QScript. The following window will appear:

Select the type of EasyLanguage study you are trying to convert. If it's a function, you'll be asked for the name. Click OK, and your code will be automatically converted to QScript.

In our experience 70-80% of EasyLanguage can be converted with no extra required work. The other 20-30% requires a few little changes here and there. If you know EasyLanguage already, you shouldn't have any trouble understanding QScript, as the two are very similar.

Make sure to read over the source code once it has been converted. Sometimes the converter will insert comments to warn you of difficulties it had. These should stand out pretty clearly. Also make sure to check the error box at the bottom of the editor for warning messages.


Functions

A function is written exactly like a script, but it is used as a plug in to other scripts rather than something the software will plot. Functions may take inputs from outside themselves, and usually (but don't have to) return a value.

Anytime you have a calculation that you use over and over again, you have a good candidate for a function. Let's say we liked to use simple moving averages. Rather than always recalculating the average when we needed to plot one, we could write a function that would do that for us. Once we had a function, we could simply call it from our script like this:

plot1=average(close,10);

This function would calculate the average close over the last 10 days for us, and would return the value. Let's write that function now:

input: price, length;

avg = 0;

for (i = 0 to length - 1 by 1)

avg += price[i];

avg /= length;

return avg;

There are two things to note about this function. First, we have inputs at the top that we can use to pass values into the function with. Function inputs do not need default values as indicator inputs do. Secondly, we have a return statement at the end. This is the value that our function will return to the calling program. If your function doesn't return a value, you'll still need a return statement at the end, but it won't have any arguments:

return;

Functions can only return one value, but you can get around this limitation by passing in reference arguments as the inputs.


Shortcut Operators

Shortcut operators are condensed operators that replace commonly used constructs. You don't need to use them, but they come in handy when you start doing a lot of programming.

+=

a = a + 3;

becomes...

a += 3;

-=

a = a - 2;

becomes...

a -= 2;

*=

a = a * 4;

becomes...

a *= 4;

/=

a = a / 5;

becomes...

a /= 5;

^=

a = a ^ 2;

becomes...

a ^= 2;


References

A reference is a special kind of variable that doesn't hold any data on it's own, but simply points to the data that some other variable holds. Another name for references are aliases, because a reference acts as an alias for another variable.

To create a reference, use the & operator before the variable name.

For example,

a = &b;

...would make a an alias of b. It is like having two variable names for the same piece of data. Look at the following code and commentary for a practical demonstration:

a = 7; # variable "a" is equal to 7

b = &a; # variable b is an alias to variable a

print a; # prints "7"

print b; # prints "7"

b = 2;

print a; # prints "2" !

a = 3;

print b; # prints "3" !

The important thing to remember is that changing the value of b also changes the value of a in the code above. This is what references are all about.

So when would we ever need this? Good question. The reason references can be valuable is when it comes to passing variables to functions.

Let's say we had a simple function that just added one to the input and returned the value:

# our "addone" function:

input: myinput;

myinput = myinput + 1;

return myinput;

So if we called this in an indicator:

a = 7;

print addone(a); # prints 8

print a; # prints 7

Notice that the value of a stays at 7, even though the input to "addone" gets changed during the function call.

Now consider passing our input in by reference:

a = 7;

print addone(&a); # prints 8

print a; # also prints 8!

This code is the same, except for the fact that we're passing a reference to a into "addone". So when we enter into our function, we're actually changing the value of a itself and not just a temporary copy of it.

So references give us a way for a function to return more than one value. We can pass a whole slew of parameters in by reference and have our function set the values of each one. This is very useful for optimization or artificial intelligence functions that need to return many weights and error values back to a main program for further processing.


Math Operators

These operators are used to perform mathematical operations.

+ operator. Adds two numbers together.

- operator. Subtracts the second operand from the first.

* operator. Multiplies two numbers together.

/ operator. Divides the first operand by the second.

^ operator. Raises a number to a power. 2^3 = 8.


Built-in Functions and Keywords

The following is a list of built-in functions/keywords that will be recognized by the QScript interpreter. Click on an individual item for more information.

If you are looking for dot functions , colorbar functions , text functions , or trendline functions , those functions are listed on their own pages.

Astro:

astro

astro_declination

astro_declinationUT

astro_location

astro_locationUT

astro_riseset

astro_star

astro_starUT

astrotrader_energy

astroUT

calc_ashtakavarga_bindus

cusp_declination

cusp_declinationUT

julianday

julian_to_year

julian_to_month

julian_to_day

julian_to_time

General:

alert

ask_volume

barsback

barnum_to_offset

barnumber

bid_volume

clearlog

close

colorN

delete_script

execute

getdata

get_regex_end

get_regex_start

goto

high

iff

length

low

max

min

offset_to_barnum

open

open_interest

plotN

pop

print

push

remove

random

reload_script

return

reverse

screencapture

shift

sleep

spawn

socketsend

sort

string

styleN

tick_volume

thicknessN

to_double

to_int

to_string

undef

userid

unshift

volume

webupload

Date and Time:

currentday

currentmonth

currentseconds

currenttime

currentyear

date_to_bar

day

dayofweek

month

time

year

Chart Information:

background_color

bar_compression

bars_per_day

chart_high

chart_low

days_onscreen

endtime

first_plot_bar

font_color

grid_color

last_bar_on_chart

last_plot_bar

mousedown

price_color

recalculate_all

rt_updating

scale_type

square_mult

square_options

starttime

symbol_name

update_color

updating_bar

use_holiday_list

Interactive Brokers Interface:

IB_AverageFill

IB_CancelAll

IB_CancelOrder

IB_GetAccountValue

IB_GoMarketAtTime

IB_MarketPosition

IB_OrderStatus

IB_PlaceOrder

PFG Interface:

PFG_AccountBalance

PFG_AverageFill

PFG_CancelAll

PFG_CancelOrder

PFG_GoMarketAtTime

PFG_MarketPosition

PFG_OrderExists

PFG_PlaceOrder

Math:

abs

acos

asin

atan

atan2

ceiling

cos

exp

floor

frac

int

ln

log10

mod

round

sin

sqrt

tan

File Manipulation:

file_delete

file_exists

file_read

file_write

String Manipulation:

join

split

strdel

strlen

strlower

strpos

strtrim

strupper

substr

System Testing:

BarsSinceEntry

Buy

CancelAll

CancelOrder

EntryPrice

EquityCurve

ExitLong

ExitShort

FillAction

FillBar

FillPrice

FillQty

MarketPosition

NextOpen

NumTrades

OpenEquity

Sell

SetOCOTag

TradeResult

WasOrderFilled

Drawing Object Creation:

canvas_arc

canvas_ellipse

canvas_lineto

canvas_movepen

canvas_pencolor

canvas_penstyle

canvas_penwidth

canvas_rectangle

canvas_text

canvas_textcolor

canvas_textheight

canvas_textsize

canvas_textwidth

hotspot_to_bar

hotspot_to_pixelx

hotspot_to_pixely

hotspot_to_price

Gann Functions:

Price_to_SQ9

Price_to_NumSq

Ready-Made QScripts:

AccDist

ActionZones

Adaptive_BZone

Adaptive_SZone

ADX

Average

BollingerBand

CCI

CMO

DMI

DMIMinus

DMIPlus

ExBars1

ExBars2

FastD

FastK

FractalTrend

FractalTrendShort

Highest

HighestBar

LeastSquares

Lomb_Cycle

Lomb_Phase

Lomb_Probability

Lowest

LowestBar

MACD

Momentum

NatalForecast

NineFive

Parabolic

Parabolic2

PercentR

PFE

Predict

RSI

SavGol

SlowD

SlowK

SmartMoneyIndex

StdDev

Summation

TLSlope

TLValue

TrueHigh

TrueLow

TrueRange

UltraMom

Waverage

Xaverage

Reserved Words:

Color List

Plot Style List

History59 Commands:

History59_Start

History59_Stop


Regular Expressions

A regular expression is a way of specifying a pattern that the interpreter will search for in the price data. They are extremely powerful, and complicated patterns that take pages of code in other languages can be specified in only a few lines of code when converted to regular expressions.

Overview

When we specify a regular expression, what we are doing is describing a price pattern to the interpreter in a special way. You need to break the pattern down into bars, just like a bar chart. Don't pay attention to bar length - bar1 can be 10 bars and bar2 only 3 bars - what is important is that each bar represents one leg of the pattern.

For example, if we were looking for a pivot pattern, where the middle bar has a higher high than the bar on either side, we would be talking about a bar pattern like this:

This idealized pattern could be used for all pivot highs, no matter what the individual width of the bars really was. So a bar with a high higher than 10 bars to the left and 6 bars to the right would also be described by this pattern.

What the regular expression engine can do for you is vary the bar widths and search parameters for this pattern to find an exact pattern or a bunch of patterns that are close to the ideal version.

Using Pat(...)

All regular expressions are evaluated using the pat( ) function. Simply pass the regular expression description in as the parameter to this function. Pat will evaluate the regular expression and return true if a match has been found on the current bar, or false if there was no match.

The way you write a regular expression is by specifying the important relationships between the individual portions of the pattern. Let's start with a very simple example. We want to find a group of bars such that the close of the group is greater than the open. We can describe this pattern using one idealized bar:

The actual regular expression would look like this:

pat(close>open {1})

There are two important things contained inside the function above. First is the ideal bar description, which is "close>open". The second is the length parameter "{1}". The "1" inside the brackets means that we should search for a pattern with a length of 1 bar. So this particular regular expression would return true for every bar that had a close greater than an open, and false otherwise.

We can search for any length pattern we choose, and can even do ranges.

pat(close>open {4:8})

...would search for all 4 to 8 bar patterns where the close was greater than the open.

The pattern shown above is one pattern that would have been identified by the regular expression. It is a 6 bar pattern that fits the close > open criteria.

We can specify more than one bar to our regular expression. If we wanted to use the first example of finding a bar with a higher high than the highs of the bars to the left and right, the regular expression would be:

pat({1}, high>high[1] {1}, high<high[1] {1})

This is a little more complicated. There are three parts to this pattern corresponding with the three bars we are looking for:

Bar1: {1}

Bar2: high>high[1] {1}

Bar3: high<high[1] {1}

So bar1 contains no description. We just want a bar that is 1 bars long. Bar2 is a bar with a high higher than the high of the bar before it. High[1] in this case refers to the highest bar in pattern 1.

Bar3 is a bar with a high lower than the bar before it. High[1] refers to the highest bar in pattern2.

Notice the difference in using offsets when compared to normal QScript. Each bar is only concerned with it's relationship to the other bars. We used "high" and "high[1]" in both bar2 and bar3, but they each referred to something different. Remember that all comparisons in a regular expression are from the point of view of the particular leg of the pattern they represent.

Let's increase the lengths:

pat( {5:10}, high>high[1] {1}, high<high[1] {5:10} )

Breaking this down we get:

Bar1: {5:10}

Bar2: high>high[1] {1}

Bar3: high<high[1] {5:10}

So we are looking for 5 to 10 bars, then a bar with a high higher than the highest high of that 5 to 10 bars, then another 5 to 10 bars with a highest high lower than the bar before. It's hard to write that in a clear way! Here's a picture:

This is an example of one pattern that would have been found by the regular expression.

More on Offsets and Data

Normal data words such as close, open, high, and low, take on a different meaning inside a regular expression. They don't refer to individual bars anymore, but the data points describing the current pattern.

So it's like the entire pattern gets squashed into one bar as far as the data points are concerned.

It's important to note that if a data offset goes farther back than the pattern has legs, then it reverts to a single bar reference. Consider the following pattern:

pat( close>close[1] {3}, close>close[1] {3} )

Breaking it down we get:

Bar1: close>close[1] {3}

Bar2: close>close[1] {3}

In bar 1, we have the data "close" and "close[1]". "Close" refers to the close of the first 3 bar pattern. "Close[1]" normally refers to the close of the pattern one leg back, but since this is the first leg of the pattern there are no other legs to go back. So in this context, close[1] refers to the close of the bar right before this leg began. Close[2] would be the close of the bar 2 bars before the pattern match.

In bar2, we have "close" and "close[1]" again. "Close" refers to the close in the second 3 bar pattern. "Close[1]" refers to the close of the first 3 bar pattern.

So the important point to remember is that if you reference data outside the pattern, you revert to a bar-by-bar system just as you are used to using in QScript.

Patterns on Variables

You don't have to use regular expressions on only the price bars. You can look for patterns in your variables as well. Since each leg of the pattern can be made up of many bars, variables have open, high, low, and close data just as price does. If we let "avg" be our moving average calculation, then:

high of avg is the highest value of "avg" in the current leg.

low[1] of avg is the lowest value of "avg" in the previous leg.

low of avg[1] is another way of writing the last sentence.

open of avg is the value of "avg" on the first bar of this leg of the pattern.

Aside from that, everything else is the same. So our pivot pattern using a moving average would look something like this:

avg = average(c,10);

if ( pat( {5:10}, high of avg>high[1] of avg {1}, high of avg<high of avg[1] {5:10} ) )

{

...match is successful - do something...

}

Pattern Details

Once a match has been found, we can get information back about the pattern that the interpreter found. We can do this using two special functions:

get_regex_start( )

get_regex_end( )

These functions return the bar number of the start and end of a particular pattern match. They only work with the most recent pattern match, so if you need this information, make sure to get it before you search for another pattern.

For example, if we matched a three section pivot pattern as discussed above, we could find the bar numbers of all sections using these two functions.

start = get_regex_start(1); # finds bar number of first bar in leg 1

stop = get_regex_end(1); # finds bar number of last bar in leg 1

start2 = get_regex_start(2); # finds bar number of first bar in leg 2

Notice that section numbers begin with 1, not 0 like in arrays!

Constraints

It is usually the case that a particular regular expression matches more than one pattern at a time. In the pivot example given above, we not only matched the pattern with lengths 5-1-8 as shown in the picture. We also matched 6-1-8, 7-1-8, 8-1-8, etc. There were quite a few matches on that particular bar.

What constraints allow you to do is filter the matched patterns in a particular way. For example, lets say we were looking for the longest pattern we could find where the close was greater than the open.

If we just use...

pat( close>open {5:20} )

...we are not guaranteed to find the longest pattern possible. If we need to use the pattern details for a particular indicator, we might not want the short patterns unless they are the only ones available.

In this case, we can use a constraint. Constraints follow the main body of the regular expression, and must follow after two tilde characters: ~~.

So writing...

pat( close>open {5:20} ~~ maximize)

...would return the largest match for the pattern. The "maximize" keyword tells the interpreter that we want the longest match possible. There is also a minimize keyword:

pat( close>open {5:20} ~~ minimize)

This would return the smallest match possible. You could still get a large match, but only when the pattern failed on all the other pattern lengths.

You can also set up individual section constraints. Section lengths can be accessed using the section number preceded by the dollar sign. So $1 is the length of section 1.

Consider the following pattern:

pat( close > open {2:5}, close < open {2:5})

This regular expression searches for two 2-5 bar patterns. The first has an upclose and the second has a down close. Although each pattern can be a minimum of 2 bars long, we might only be interested in patterns with a total length of 5 bars. But we still want to allow 2 bar patterns on each end, though. We can use a constraint to accomplish this:

pat( close > open {2:5}, close < open {2:5} ~~ ($1+$2) >= 5 )

A pattern match is only possible if the constraint "($1+$2) >= 5" is true. $1 refers to the bar length of section 1 and $2 refers to the bar length of section 2. They must add up to be greater or equal to 5 for a match to be returned.

You can also constrain against data elements (like open, high, etc) if you need to, but remember that in the constraints section, offsets are regular QScript offsets, not section numbers!


Transferring Scripts

You can share QScripts between different copies of Wave59 using special transfer protocols built into the software.

Click here for information about sending a script to another computer.

Click here for information about receiving a script from another computer.


Print

Syntax:

print arg1, arg2, ..., argN;

Description:

Print statements can be used to write information to the script log . Enter the items to be printed as a comma-separated list following the print statement. If you end the print statement with a comma and no following argument, the next print statement will begin where the current one left off. Otherwise, each print statement will be positioned on it's own line.

Example:

print 1, "hi there", 3; # prints: 1 hi there 3

# the following two statements print "45" because of the ending comma on the first print statement.

print 4,;

print 5;


Goto

Syntax:

goto LABEL;

Description:

A goto statement jumps immediately to the specified label and continues program execution from that location. A label is simply a user defined word followed by a colon. Labels should sit on their own lines.

Example:

a = 5;

goto JUMP;

a = 6; # this statement will not be executed

JUMP:

print a; # prints "5"


Return

Syntax:

return;

return argument1;

Description:

Return statements are used inside functions to specify what value the function should return. When a return statement is hit, the program exits execution of the function and returns the specified value to the calling program. More than one return statement may be used in a given function (inside blocks, etc.).

Example:

avg = average(c,10);

return avg; # returns "avg" to the calling program


Year

Syntax:

year[offset]

Description:

Returns the year of the given bar in the full 4-digit format.

Example:

a = year; # a holds the year of the current bar

a = year[1]; # a holds the year of the bar right before the current bar


Month

Syntax:

month[offset]

Description:

Returns the month of the given bar. 1 is January and 12 is December.

Example:

a = month; # a holds the month of the current bar

a = month[1]; # a holds the month of the bar right before the current bar


Day

Syntax:

day[offset]

Description:

Returns the day of the month of the given bar.

Example:

a = day; # a holds the day of the current bar

a = day[1]; # a holds the day of the bar right before the current bar


Time

Syntax:

time[offset]

Description:

Returns the ending time of the given bar in military time (0 - 2359).

Example:

a = time; # a holds the time of the current bar

a = time[1]; # a holds the time of the bar right before the current bar


Volume

Syntax:

volume[offset]

Description:

Returns the volume of the given bar. Other volume types available are: ask_volume , bid_volume , and tick_volume .

Example:

a = volume; # a holds the volume of the current bar

a = volume[1]; # a holds the volume of the bar right before the current bar


Barnumber

Syntax:

barnumber[offset]

barnum[offset]

Description:

Returns the bar number of the given bar. The very first bar on the chart is 1.

Example:

a = barnum; # a holds the current bar number

a = barnumber[1]; # a holds the bar number of the previous bar


Undef

Syntax:

undef

Description:

Undef is a value that means "no value". All variables start out as undefined (undef) variables, and you'll receive and error if you try to use an undefined variable in an expression.

Example:

a = undef; # a is now undefined


Sin

Syntax:

sin(x)

Description:

Returns the sine of the argument in degrees.

Example:

a = sin(90); # a equals 1


Cos

Syntax:

cos(x)

Description:

Returns the cosine of the argument in degrees.

Example:

a = cos(90); # a equals 0


Tan

Syntax:

tan(x)

Description:

Returns the tangent of the argument in degrees.

Example:

a = tan(45); # a equals 1


ASin

Syntax:

asin(x)

Description:

Returns the arcsine of the argument in degrees.

Example:

a = asin(1); # a equals 90


ACos

Syntax:

acos(x)

Description:

Returns the arccosine of the argument in degrees.

Example:

a = acos(0); # a equals 90


ATan

Syntax:

atan(x)

Description:

Returns the arctangent of the argument in degrees. The range is -90 to +90 degrees.

Example:

a = atan(0); # a equals 0


ATan2

Syntax:

atan2(x,y)

Description:

Returns the arctangent of x/y in degrees.

Example:

a = atan2(4,3); # a equals 53.13


Abs

Syntax:

abs(x)

Description:

Returns the absolute value of the argument.

Example:

a = abs(-1); # a equals 1


Sqrt

Syntax:

sqrt(x)

Description:

Returns the square root of the argument.

Example:

a = sqrt(4); # a equals 2


Ln

Syntax:

ln(x)

Description:

Returns the natural log of the argument.

Example:

a = ln(1); # a equals 0


Log10

Syntax:

log10(x)

Description:

Returns the log (base 10) of the argument.

Example:

a = log10(5); # a equals 0.698


Exp

Syntax:

exp(x)

Description:

Returns the exponential of the argument.(E^x)

Example:

a = exp(1); # a equals 2.7182


File_Exists

Syntax:

file_exists(filename)

Description:

Returns true if the file exists, false otherwise.

Example:

a = file_exists("c:\mytextfile.txt"); # a equals true if "mytextfile.txt" exists on the c drive.


File_Read

Syntax:

file_read(array, filename)

Description:

Reads the contents of the file and places them in the given array . Each array element represents one line of the file. Note that this function does not erase what is already in the array, but adds the file contents to the end. If the array contains data from previous work, and you wish for it just to contain the contents of the file, make sure to call clear(...) to empty the array before the file is read.

Example:

clear(myarray); # empties the array of all current data

file_read(myarray,"c:\myfile.txt");


File_Write

Syntax:

file_write(filename, arg1, arg2, ..., argN)

Description:

Appends the given arguments to the file. All arguments will be combined and fit on the same line of the file. If the argument list ends with a comma rather than an argument, the next file_write will continue on the same line of the file rather than on a new one.

Example:

file_write("c:\myfile.txt",1,2,3); # appends "123" to the end of myfile.txt


File_Delete

Syntax:

file_delete(filename)

Description:

Deletes the file. Returns true if the operation was successful, false if not.

Example:

a = file_delete("c:\myfile.txt"); # a is true if myfile.txt was able to be deleted


StrPos

Syntax:

strpos(string, substring)

Description:

Searches string for substring and returns the position of the first character of substring if found. Always returns the position of the first string starting from the beginning of the string to be searched. Strings are 1-based, so a value of 1 means the very first letter of the string. If the substring could not be found, the function returns -1.

Example:

a = strpos("the big ape","big"); # a equals 5


SubStr

Syntax:

substr(string, index1, length)

Description:

Returns the portion of string starting at index1 and going for length characters. The first character in a string is at index 1.

Example:

a = substr("Manhattan",4,3); # a equals "hat"


StrLen

Syntax:

strlen(string)

Description:

Returns the length of string in characters.

Example:

a = strlen("hello"); # a equals 5


StrDel

Syntax:

strdel(string, index1, length)

Description:

Returns string with the substring starting at index1 and running for length characters deleted. The first character in a string is at index 1.

Example:

a = strdel("one plus one",4,6); # a equals "oneone"


StrLower

Syntax:

strlower(string)

Description:

Returns an all lower-case version of string.

Example:

a = strlower("Hi! Blah BLAH"); # a equals "hi! blah blah"


StrUpper

Syntax:

strupper(string)

Description:

Returns an all upper-case version of string.

Example:

a = strlower("Hi! Blah BLAH"); # a equals "HI! BLAH BLAH"


StrTrim

Syntax:

strtrim(string)

Description:

Returns a version of string with all leading and trailing spaces and control characters removed.

Example:

a = strtrim(" hi "); # a equals "hi"


Join

Syntax:

join(delimiter, arg1, arg2, ..., argN)

Description:

Combines all arguments together into one string . Arguments are separated by the delimiter string.

Example:

a = join("-","a","b","c",5); # a equals "a-b-c-5"


Split

Syntax:

split(array, string, delimiter)

Description:

Splits string into pieces and stores the pieces in the array. String will be split according to the passed in delimiter.

Example:

a = split(myarray,"here are some words."," ";

# myarray now contains 4 strings: {here,are,some,words.}


String

Syntax:

string(number, digits)

Description:

Converts number to a string with the given number of digits.

Example:

a = string(3.14159,2); # a equals "3.14"


Mod

Syntax:

mod(x, y)

Description:

Returns the remainder from dividing x by y.

Example:

a = mod(4,3); # a equals 1 (3 goes into 4 one time with a remainder of one)

a = mod(3,4); # a equals 3 (4 goes into 3 zero times with a remainder of three)


Int

Syntax:

int(x)

Description:

Returns the integer portion of x.

Example:

a = int(3.14159); # a equals 3


Frac

Syntax:

frac(x)

Description:

Returns the fractional portion of x.

Example:

a = frac(3.1415); # a equals 0.14159


Round

Syntax:

round(number, decimals)

Description:

Rounds the given number to the specified number of decimal places.

Example:

a = round(2.888,1); # a equals 2.9


Floor

Syntax:

floor(x)

Description:

Returns the largest integer not greater than x. An integer is a whole number.

Example:

a = floor(3.1415); # a equals 3


Ceiling

Syntax:

ceiling(x)

Description:

Returns the smallest integer not less than x. An integer is a whole number.

Example:

a =ceiling(3.1415); # a equals 4


ClearLog

Syntax:

clearlog( )

Description:

Clears the script log .

Example:

clearlog();


Max

Syntax:

max(arg1, arg2, ..., argN)

Description:

Returns the largest number in the list of arguments.

Example:

a = max(1, 2, -1, 7, 3); # a equals 7


Min

Syntax:

min(arg1, arg2, ..., argN)

Description:

Returns the smallest number in the list of arguments.

Example:

a = min(1, 2, -1, 7, 3); # a equals -1


UserID

Syntax:

userid

Description:

Returns the unique customer number for the particular installation of the software. Each user has a different number, which can be found by clicking Help - About.

Example:

a = userid; # a equals some number unique to this user


DayOfWeek

Syntax:

dayofweek(year, month, day)

Description:

Returns the weekday of the given date. 1 is Monday, 7 is Sunday. QScript will recognize names of the weekday, so you don't need to remember which day is which number.

Example:

if ( dayofweek(year, month, day) == Monday )

{

...

}


Random

Syntax:

random(x)

Description:

Returns a random integer number between 0 and x-1.

Example:

a = random(10); # a will be a random number in the range 0 to 9


Dots

QScript contains a number of special plotting functions that you can use in your studies. Dots are one kind of drawing tool that can be used to show off special situations, important levels, or simply as an alternative to using lines on a chart:

The parabolic indicator on the chart above was plotted using dots.

When you plot a dot on the chart, this dot is stored in a special array that the interpreter will keep track of. Each dot can be referred to using it's reference number, which is returned by the initial plotting function. This means that you can modify the properties of older dots later on in the code by using their individual reference numbers. A list of all dot manipulation functions follows.

plot_dot(barnumber, price, color, width)

This function plots a dot on the chart at the specified price and barnumber. Click here for a list of colors. Width is how thick the dot should be, in screen pixels. This function returns a unique reference number for the dot, which should be saved if you intend to modify the dot's attributes later on.

replot_dot(ref, barnumber, price, color, width)

This function allows you to change the properties of a dot on the chart. Ref refers to the reference number of the dot you wish to modify.

dot_delete(ref)

Deletes the dot object at the given reference number.

dot_is_valid(ref)

Returns true if the argument is a valid reference number for a dot, false otherwise.

get_dot_max_ref( )

Returns largest reference number of all dots plotted with the indicator.

get_dot_min_ref( )

Returns smallest reference number of all dots plotted with the indicator.

*

get_dot_color(ref)

Returns the color of the dot associated with the given reference number.

set_dot_color(ref, color)

Changes the color of the dot referred to by the given reference number.

*

get_dot_width(ref)

Returns the width of the dot associated with the given reference number.

set_dot_width(ref, width)

Changes the width of the dot referred to by the given reference number.

*

get_dot_bar(ref)

Returns the bar number of the dot associated with the given reference number.

set_dot_bar(ref, bar)

Changes the bar number of the dot referred to by the given reference number.

*

get_dot_price(ref)

Returns the price of the dot associated with the given reference number.

set_dot_price(ref, price)

Changes the price of the dot referred to by the given reference number.

*

get_num_dots( )

Returns the total number of dots on the chart plotted by the current indicator.


Trendlines

QScript contains a number of special plotting functions that you can use in your studies. Trendlines are one kind of drawing tool available to you from within your QScript.

When you plot a trendline on the chart, the trendline is stored in a special array that the interpreter will keep track of. Each trendline can be referred to using it's reference number, which is returned by the initial plotting function. This means that you can modify the properties of older trendlines later on in the code by using their individual reference numbers. A list of all trendline manipulation functions follows:

trendline(bar1, price1, bar2, price2, color)

Plots a trendline starting at bar1 and price1, and ending at bar2 and price2. Bar1 and bar2 refer to actual bar numbers. Color determines the color of the trendline. Click here for a list of available colors. Returns a unique reference number for the new trendline that you should save if you intend to modify this trendline.

tl_delete(ref)

Deletes the trendline object at the given reference number.

tl_is_valid(ref)

Returns true if the argument is a valid reference number for a trendline, false otherwise.

get_tl_max_ref( )

Returns largest reference number of all trendlines plotted with the indicator.

get_tl_min_ref( )

Returns smallest reference number of all trendlines plotted with the indicator.

*

tl_extend_left(ref, true/false)

Sets the extension of the left end of the trendline. If the second parameter is true, the trendline will extend to the edge of the screen. Whether or not a trendline is extended does not affect the location of bar1, bar2, price1, or price2.

tl_extend_right(ref, true/false)

Identical to the function above, but operates on the right end of the trendline.

*

get_tl_color(ref)

Returns the color of the trendline corresponding to the given reference number.

set_tl_color(ref, color)

Changes the color of the trendline corresponding to the given reference number.

*

get_tl_size(ref)

Returns the size of the trendline corresponding to the given reference number.

set_tl_size(ref, size)

Changes the width of the trendline corresponding to the given reference number.

*

get_tl_bar1(ref)

Returns the barnumber of the first bar of the trendline corresponding to the given reference number.

set_tl_bar1(ref, bar)

Changes the bar number for the first bar of the trendline corresponding to the given reference number.

*

get_tl_price1(ref)

Returns the price at the first bar of the trendline corresponding to the given reference number.

set_tl_price1(ref, price)

Changes the price at the first bar of the trendline corresponding to the given reference number.

*

get_tl_bar2(ref)

Returns the barnumber of the last bar of the trendline corresponding to the given reference number.

set_tl_bar2(ref, bar)

Changes the barnumber of the last bar of the trendline corresponding to the given reference number.

*

get_tl_price2(ref)

Returns the price at the last bar of the trendline corresponding to the given reference number.

set_tl_price2(ref, price)

Changes the price at the last bar of the trendline corresponding to the given reference number.

*

get_tl_style(ref)

Returns the style of the trendline corresponding to the given reference number.

set_tl_style(ref, style)

Changes the style of the trendline corresponding to the given reference number. Note that by setting a trendline to style "ps_clear", the trendline is effectively erased from the user's perspective.

*

get_num_trendlines( )

Returns the total number of trendlines on the chart plotted by the current indicator.

*

get_tl_value(ref, bar)

Returns the value of the trendline corresponding to the given reference number at the specified bar. For the purpose of this function, you may assume that all trendlines extend infinitely in both directions on the chart.


Text

QScript contains text objects, which let you programmatically add and mainpulate text on a chart.

When you plot a text on the chart, the trendline is stored in a special array that the interpreter will keep track of. Each text object can be referred to using it's reference number, which is returned by the initial plotting function. This means that you can modify the properties of older text objects later on in the code by using their individual reference numbers. A list of all text manipulation functions follows:

text(bar, price, string, color, style, size)

This function plots new text on the chart at the specified bar number and price. The text that will be plotted is given by string. Click here for a list of available colors. The style parameter can be one of the following constants: tx_center, tx_right, or tx_left. This determines how the text will be plotted in relation to the given bar. Tx_center centers the text, tx_right places the right edge of the text at the bar, and tx_left places the left edge of the text at the bar. Size is the font size of the text. This function returns a unique reference number for the text object that you should save if you intend on modifying the text later on.

text_reset(ref, bar, price, string, color, style, size)

Resets all parameters of the text object corresponding to the given reference number, ref.

text_delete(ref)

Deletes the text object at the given reference number.

text_is_valid(ref)

Returns true if the argument is a valid reference number for a text object, false otherwise.

get_text_max_ref( )

Returns largest reference number of all text objects plotted with the indicator.

get_text_min_ref( )

Returns smallest reference number of all text objects plotted with the indicator.

*

text_getbar(ref)

Returns the bar number of the text object corresponding to the given reference number.

text_setbar(ref, bar)

Changes the bar number of the text corresponding to the given reference number.

*

text_getsize(ref)

Returns the font size of the text object corresponding to the given reference number.

text_setsize(ref, size)

Changes the font size of the text corresponding to the given reference number.

*

text_getstyle(ref)

Returns the style of the text object corresponding to the given reference number.

text_setstyle(ref, style)

Changes the style of the text corresponding to the given reference number. Use one of the constants tx_center, tx_right, or tx_left.

*

text_getcolor(ref)

Returns the color of the text object corresponding to the given reference number.

text_setcolor(ref, color)

Changes the color of the text corresponding to the given reference number.

*

text_getprice(ref)

Returns the price of the text object corresponding to the given reference number.

text_setprice(ref, price)

Changes the price of the text corresponding to the given reference number.

*

text_getstring(ref)

Returns the string of the text object corresponding to the given reference number.

text_setstring(ref, string)

Changes the string of the text corresponding to the given reference number.

*

get_num_text( )

Returns the number of text objects plotted on the chart by the current indicator.


ColorBars

Colors bars are special drawing tools that let you paint the price bars different colors. The following chart was created using colorbars based on the SmartMoneyIndex function:

When you create a colorbar on the chart, the colorbar is stored in a special array that the interpreter will keep track of. Each colorbar can be referred to using it's reference number, which is returned by the initial plotting function. This means that you can modify the properties of older colorbars later on in the code by using their individual reference numbers. A list of all colorbar manipulation functions follows:

colorbar(barnumber, color, width)

Changes the color of the given bar to the specified color. Click here for a list of available colors. The width parameter determines how thick to make the new bar. This function returns a unique reference number for the colorbar that you should save if you intend on modifying the text later on.

reset_colorbar(ref, bar, color, width)

Resets the attributes of the colorbar corresponding to the given reference number with the supplied parameters.

colorbar_delete(ref)

Deletes the colorbar object at the given reference number.

colorbar_is_valid(ref)

Returns true if the argument is a valid reference number for a colorbar, false otherwise.

get_colorbar_max_ref( )

Returns largest reference number of all colorbars plotted with the indicator.

get_colorbar_min_ref( )

Returns smallest reference number of all colorbars plotted with the indicator.

*

get_colorbar_color(ref)

Returns the color of the colorbar corresponding to the given reference number.

set_colorbar_color(ref, color)

Changes the color of the colorbar corresponding to the given reference number.

*

get_colorbar_width(ref)

Returns the width of the colorbar corresponding to the given reference number.

set_colorbar_width(ref, width)

Changes the width of the colorbar corresponding to the given reference number.

*

get_colorbar_bar(ref)

Returns the bar number of the colorbar corresponding to the given reference number.

set_colorbar_bar(ref, bar)

Changes the bar number of the colorbar corresponding to the given reference number.

*

get_num_colorbars( )

Returns the total number of colorbars plotted on the chart by the current indicator.


StartTime

Syntax:

starttime

Description:

Returns the start time for the chart as entered on the chart setup page. Please see Wave59 help for more information.

Example:

a = starttime; # a equals 930 for the S&P on a computer running on Eastern Time


EndTime

Syntax:

endtime

Description:

Returns the ending time for the chart as entered on the chart setup page. Please see Wave59 help for more information.

Example:

a = endtime; # a equals 1615 for the S&P on a computer running on Eastern Time


Price_Color

Syntax:

price_color

Description:

Returns the color currently selected for price. This color is set on the chart settings page. Please see Wave59 help for more information.

Example:

if (price_color == green)

{

...

}


Background_Color

Syntax:

background_color

Description:

Returns the color currently selected for the chart background. This color is set on the chart settings page. Please see Wave59 help for more information.

Example:

if (background_color == white)

{

...

}


Grid_Color

Syntax:

grid_color

Description:

Returns the color currently selected for the price axis and grid. This color is set on the chart settings page. Please see Wave59 help for more information.

Example:

if (grid_color == green)

{

...

}


Font_Color

Syntax:

font_color

Description:

Returns the color currently selected for the screen font. This color is set on the chart settings page. Please see Wave59 help for more information.

Example:

if (font_color == black)

{

...

}


Update_Color

Syntax:

update_color

Description:

Returns the color currently selected for the updating price bar. This color is set on the chart settings page. Please see Wave59 help for more information.

Example:

if (price_color == green)

{

...

}


Bar_Compression

Syntax:

bar_compression

Description:

Returns the bar compression for the current chart. A 5-minute bar chart would have a bar compression of 5. This value is set in the chart settings form. Please see Wave59 help for more information.

Example:

if (bar_compression == 5)

{

...

}


Symbol_Name

Syntax:

symbol_name

Description:

Returns the name of the symbol currently being plotted on the chart.

Example:

name = symbol_name; # might be something like "SPM01"


Chart_High

Syntax:

chart_high

Description:

Returns the price of the top of the chart.

Example:

maxp = chart_high;


Chart_Low

Syntax:

chart_low

Description:

Returns the price of the bottom of the chart.

Example:

lowp = chart_low;


Scale_Type

Syntax:

scale_type

Description:

Returns a number indicating what kind of scale the user has selected for this chart. 1 = automatic scaling, 2 = manual scaling, 3 = square scaling. See Wave59 help for more information on scaling.

Example:

scale = scale_type; # scale will be 1, 2, or 3 depending on the chart scaling


Square_Mult

Syntax:

square_mult

Description:

Returns the number entered by the user for the "square mult" scaling setting. If the chart is not on square scaling, -1 will be returned.

Example:

mult = square_mult;


Square_Options

Syntax:

square_options

Description:

Returns a number indicator which square scaling option the user has selected. 1 = bar, 2 = hour, and 3 = day. See Wave59 help for more information about scaling.

Example:

name = square_options;


RT_Updating

Syntax:

rt_updating

Description:

Returns true if the chart is set to update in real time, false if not. Turning real time updating on and off can be done from the Options menu. Please see Wave59 help for more information.

Example:

if (rt_updating == true)

{

...only do this if we're updating in real time...

}


First_Plot_Bar

Syntax:

first_plot_bar

Description:

Returns the bar number of the first bar displayed on screen.

Example:

if (first_plot_bar>10)

{

...

}


Last_Plot_Bar

Syntax:

last_plot_bar

Description:

Returns the bar number of the last bar displayed on screen.

Example:

if (last_plot_bar<100)

{

...

}


Days_OnScreen

Syntax:

days_onscreen

Description:

Returns the number of days plotted on screen. This value is set by the user in the chart settings form. For more information see Wave59 help.

Example:

ons = days_onscreen;


Bars_Per_Day

Syntax:

bars_per_day

Description:

Returns the number of bars that will be plotted in one trading day.

Example:

for (i=0 to bars_per_day by 1)

{

...

}


Updating_Bar

Syntax:

updating_bar

Description:

Returns the bar number of the currently updating bar. Note that QScripts will not be evaluated on this bar because it is constantly changing. So the last bar a QScript will be evaluated on is updating_bar-1.

Example:

if (barnumber == updating_bar - 1)

{

...last filled bar on chart...

}


Offset_to_BarNum

Syntax:

offset_to_barnum(x)

Description:

Converts the offset specified by x to a barnumber .

Example:

a = offset_to_barnum(0); # returns the barnumber for the current bar (offset = 0)

a = offset_to_barnum(1); # returns the barnumber for the previous bar (offset = 1)


BarNum_to_Offset

Syntax:

barnum_to_offset(x)

Description:

Converts a barnumber to an offset. Negative values refer to future bars.

Example:

a = barnum_to_offset(barnumber); # a holds 0, as the offset for the current barnumber is always 0

a = barnum_to_offset(56); # assuming the current bar number is 60, a would hold 4


To_Int

Syntax:

to_int(x)

Description:

Returns a forced integer conversion of x. Really only useful when writing DLLs . Click here for more on data types.

Example:

a = to_int(a); # assures us that a is an integer type


To_Double

Syntax:

to_double(x)

Description:

Returns a forced double conversion of x. Really only useful when writing DLLs . Click here for more on data types.

Example:

a = to_double(a); # assures us that a is an double type


To_String

Syntax:

to_string(x)

Description:

Returns a forced string conversion of x. Really only useful when writing DLLs . Click here for more on data types.

Example:

a = to_string(a); # assures us that a is a string type


Astro

Syntax:

astro(year, month, day, time, planet, geocentric, return_type, use_tropical)

Description:

Returns ephemeris data for an astrological body at the given time. Year, month, day, and time specify the instant we are interested in. Note that time is local time for your computer. Planet is one of the following constants, which will determine which body we are interested in:

planets:

astro_mercury

astro_venus

astro_earth

astro_moon

astro_sun

astro_mars

astro_jupiter

astro_saturn

astro_uranus

astro_neptune

astro_pluto

astro_mean_node (north)

astro_true_node (north)

astro_mean_apog

astro_oscu_apog

asteroids:

astro_ceres

astro_chiron

astro_juno

astro_pallas

astro_pholus

astro_vesta

Uranian (fictitious) planets:

astro_cupido

astro_hades

astro_zeus

astro_kronos

astro_apollon

astro_admetos

astro_vulkanus

astro_poseidon

astro_isis

astro_nibiru

astro_harrington

Geocentric is either true or false. If true, geocentric (earth-centered) positions will be returned. Otherwise heliocentric (sun-centered) positions will be returned.

A return type (return_type) must be specified to tell the interpreter what particular piece of data we're interested in. Use one of the following constants:

astro_long = planetary longitude (probably what you want)

astro_lat = planetary latitude (degrees above or below ecliptic)

astro_dist = distance from sun/earth in AU

astro_longspeed = speed of longitude change (deg/day)

astro_latspeed = speed of latitude change (deg/day)

astro_distspeed = speed of distance change (AU/day)

astro_ra = planetary right ascension (in degrees)

astro_raspeed = speed of right ascension change (deg/day)

Finally, you must specify whether the function should use tropical (western style) or sidereal positions. If use_tropical is set to true, tropical values will be returned.

Example:

print astro(1998, 1, 1, 1200, astro_moon, true, astro_long, true); # prints 321.2


AstroUT

Syntax:

astroUT(year, month, day, time, planet, geocentric, return_type, use_tropical)

Description:

Returns ephemeris data for an astrological body at the given time. Year, month, day, and time specify the instant we are interested in. Note that time is Universal Time (Greenwich). Planet is one of the following constants, which will determine which body we are interested in:

planets:

astro_mercury

astro_venus

astro_earth

astro_moon

astro_sun

astro_mars

astro_jupiter

astro_saturn

astro_uranus

astro_neptune

astro_pluto

astro_mean_node (north)

astro_true_node (north)

astro_mean_apog

astro_oscu_apog

asteroids:

astro_ceres

astro_chiron

astro_juno

astro_pallas

astro_pholus

astro_vesta

Uranian (fictitious) planets:

astro_cupido

astro_hades

astro_zeus

astro_kronos

astro_apollon

astro_admetos

astro_vulkanus

astro_poseidon

astro_isis

astro_nibiru

astro_harrington

Geocentric is either true or false. If true, geocentric (earth-centered) positions will be returned. Otherwise heliocentric (sun-centered) positions will be returned.

A return type (return_type) must be specified to tell the interpreter what particular piece of data we're interested in. Use one of the following constants:

astro_long = planetary longitude (probably what you want)

astro_lat = planetary latitude (degrees above or below ecliptic)

astro_dist = distance from sun/earth in AU

astro_longspeed = speed of longitude change (deg/day)

astro_latspeed = speed of latitude change (deg/day)

astro_distspeed = speed of distance change (AU/day)

astro_ra = planetary right ascension (in degrees)

astro_raspeed = speed of right ascension change (deg/day)

Finally, you must specify whether the function should use tropical (western style) or sidereal positions. If use_tropical is set to true, tropical values will be returned.

Example:

print astroUT(1998, 1, 1, 1200, astro_moon, true, astro_long, true); # prints 317.04


Astro_Star

Syntax:

astro_star(year, month, day, time, star_name, geocentric, return_type, use_tropical)

Description:

Returns ephemeris data for an fixed star at the given time. Year, month, day, and time specify the instant we are interested in. Note that time is local time for your computer. The star name is a string containing the name of the star to return data for.

Geocentric is either true or false. If true, geocentric (earth-centered) positions will be returned. Otherwise heliocentric (sun-centered) positions will be returned.

A return type (return_type) must be specified to tell the interpreter what particular piece of data we're interested in. Use one of the following constants:

astro_long = stellar longitude (probably what you want)

astro_lat = stellar latitude/declination (degrees above or below ecliptic)

astro_dist = distance from sun/earth in AU

astro_longspeed = speed of longitude change (deg/day)

astro_latspeed = speed of latitude change (deg/day)

astro_distspeed = speed of distance change (AU/day)

Finally, you must specify whether the function should use tropical (western style) or sidereal positions. If use_tropical is set to true, tropical values will be returned.

Example:

print astro_star(1998, 1, 1, 1200, "aldebaran", true, astro_long, true); # prints 69.76


Astro_StarUT

Syntax:

astro_starUT(year, month, day, time, star_name, geocentric, return_type, use_tropical)

Description:

Returns ephemeris data for an fixed star at the given time. Year, month, day, and time specify the instant we are interested in. Note that time is Universal Time (Greenwich). The star name is a string containing the name of the star to return data for.

Geocentric is either true or false. If true, geocentric (earth-centered) positions will be returned. Otherwise heliocentric (sun-centered) positions will be returned.

A return type (return_type) must be specified to tell the interpreter what particular piece of data we're interested in. Use one of the following constants:

astro_long = stellar longitude (probably what you want)

astro_lat = stellar latitude/declination (degrees above or below ecliptic)

astro_dist = distance from sun/earth in AU

astro_longspeed = speed of longitude change (deg/day)

astro_latspeed = speed of latitude change (deg/day)

astro_distspeed = speed of distance change (AU/day)

Finally, you must specify whether the function should use tropical (western style) or sidereal positions. If use_tropical is set to true, tropical values will be returned.

Example:

print astro_starUT(1998, 1, 1, 1200, "aldebaran", true, astro_long, true); # prints 69.76


CurrentYear

Syntax:

currentyear

Description:

Returns the 4-digit year value of the current time according to the computer clock.

Example:

if (currentyear < 1999)

{

...last bar on chart...

}


CurrentMonth

Syntax:

currentmonth

Description:

Returns the month according to the computer clock. 1 is January, 12 is December.

Example:

if (currentmonth < 12)

{

...last bar on chart...

}


CurrentDay

Syntax:

currentday

Description:

Returns the day of month according to the computer clock.

Example:

if (currentday < 10)

{

...last bar on chart...

}


CurrentTime

Syntax:

currenttime

Description:

Returns the time (military format) according to the computer clock.

Example:

if (currenttime < 1400)

{

...last bar on chart...

}


CurrentSeconds

Syntax:

currentseconds

Description:

Returns the seconds and milliseconds according to the computer clock. Milliseconds will be returned as a fraction of a second.

Example:

print currentseconds; # prints 11.273


Close

Syntax:

close[offset]

c[offset]

Description:

Returns the closing price of the given bar.

Example:

a = close; # a holds the closing price of the current bar

a = close[1]; # a holds the closing price of the previous bar


Open

Syntax:

open[offset]

o[offset]

Description:

Returns the opening price of the given bar.

Example:

a = open; # a holds the opening price of the current bar

a = o[1]; # a holds the opening price of the previous bar


High

Syntax:

high[offset]

h[offset]

Description:

Returns the highest price of the given bar.

Example:

a = high; # a holds the high price of the current bar

a = h[1]; # a holds the high price of the previous bar


Low

Syntax:

low[offset]

l[offset]

Description:

Returns the lowest price of the given bar.

Example:

a = low; # a holds the high price of the current bar

a = l[1]; # a holds the high price of the previous bar


AccDist

Syntax:

accdist( )

Description:

This is Larry William's Accumulation-Distribution indicator.

Example:

plot1 = accdist();


ADX

Syntax:

adx(length)

Description:

This is Welles Wilder's classic trend indicator. This was a precursor to our proprietary Fractal Trend Index .

Example:

plot1 = adx(14);


Fractal Trend

Syntax:

fractaltrend(price, depth)

Description:

This is our proprietary fractal trend indicator. Price is the price series to use when computing the trend index, and depth acts as a smoothing factor.

Example:

plot1 = FractalTrend(close, 8);


Average

Syntax:

average(price, length)

Description:

This is a simple average. Price is summed up over length bars, then divided by length to obtain the average.

Example:

plot1 = average(close, 10);


BollingerBand

Syntax:

BollingerBand(price, length, stddev, updn)

Description:

This is John Bollinger's famous band study. Price is the price series to use to calculate the bands, length is the look back period, stddev is the number of standard deviations above or below price to place the band, and updn specifies whether to return the upper band or the lower one. Updn should be greater than 0 for the upper band, less than 0 for the lower.

Example:

plot1 = bollingerbands(close, 20, 2.2, 1); # plots a band above price


CCI

Syntax:

cci(length)

Description:

The Commodity Channel Index.

Example:

plot1 = cci(14);


CMO

Syntax:

cmo(length)

Description:

Chande's Momentum Oscillator.

Example:

plot1 = cmo(14);


DMI

Syntax:

dmi(length)

Description:

This is Welles Wilder's DMI combined DMI indicator. It uses both DMIPlus and DMIMinus to obtain a final indicator value.

Example:

plot1 = dmi(14);


DMIMinus

Syntax:

DMIMinus(length)

Description:

This is Welles Wilder's DMI- indicator.

Example:

plot1 = dmiminus(14);


DMIPlus

Syntax:

DMIPlus(length)

Description:

This is Welles Wilder's DMI+ indicator.

Example:

plot1 = dmiplus(14);


Adaptive_BZone

Syntax:

Adaptive_BZone(osc, perc, length)

Description:

This is an oscillator zone that gets dynamically set using the recent behavior of the underlying oscillator. It finds a level such that the value of osc was over the level only perc percentage of times in the last length bars.

Example:

plot1 = adaptive_bzone(rsi(14), 0.2, 50);

# returns the level that the rsi was over only 20% of time in the last 50 bars


Adaptive_SZone

Syntax:

Adaptive_SZone(osc, perc, length)

Description:

This is an oscillator zone that gets dynamically set using the recent behavior of the underlying oscillator. It finds a level such that the value of osc was below the level only perc percentage of times in the last length bars.

Example:

plot1 = adaptive_szone(rsi(14), 0.2, 50);

# returns the level that the rsi was under only 20% of time in the last 50 bars


ExBars1

Syntax:

ExBars1(qual, length)

Description:

Returns the first Exhaustion Bar study. A return value of 1 means a buy signal has been triggered, -1 means a sell signal has been triggered, and 0 means no signals for the current bar. Qual and length are length parameters for two patterns that need to be present for a signal. For more information, read about Exhaustion Bars in Wave59 help as well.

Example:

plot1 = exbars1(6, 30);


ExBars2

Syntax:

ExBars2(qual)

Description:

Returns the second Exhaustion Bar study. A return value of 1 means a buy signal has been triggered, -1 means a sell signal has been triggered, and 0 means no signals for the current bar. Qual is a qualification parameter for a patterns that needs to be present for a signal. For more information, read about Exhaustion Bars in Wave59 help as well.

Example:

plot1 = exbars2(5);


FastD

Syntax:

FastD(length)

Description:

Stochastic FastD calculation.

Example:

plot1 = FastD(14);


FastK

Syntax:

FastK(length)

Description:

Stochastic FastK calculation.

Example:

plot1 = FastK(14);


FractalTrendShort

Syntax:

FractalTrendShort(price, depth)

Description:

This is a shorter-term version of our proprietary fractal trend indicator. Price is the price series to use when computing the trend index, and depth acts as a smoothing factor.

Example:

plot1 = FractalTrendShort(close, 8);


Highest

Syntax:

highest(price, length)

Description:

Returns the highest price value over the last length bars.

Example:

plot1 = highest(high, 8);


HighestBar

Syntax:

highestbar(price, length)

Description:

Returns the bar number of the highest price over the last length bars.

Example:

plot1 = highestbar(low, 8);


LeastSquares

Syntax:

LeastSquares(price, length, target)

Description:

Returns the value of a line fitted to price using regression by least squares. Length refers to the number of bars back to use in the calculation, and target refers to which particular value of the line to return the value of. Target of 0 will return the very end of the line, negative numbers return the value that many bars to the right (future), and positive values return the value of the line that many bars to the left of current (past).

Example:

plot1 = LeastSquares(close, 8, -1); # returns the value of the line for the next bar after current


Lowest

Syntax:

lowest(price, length)

Description:

Returns the lowest price value over the last length bars.

Example:

plot1 = lowest(low, 8);


LowestBar

Syntax:

lowestbar(price, length)

Description:

Returns the bar number of the lowest price over the last length bars.

Example:

plot1 = lowestbar(low, 8);


MACD

Syntax:

macd(price, fastma, slowma)

Description:

Returns the value of the MACD indicator. This is the difference between two moving averages. The length of the fast average is given by fastma, and the length of the slower by slowma.

Example:

plot1 = macd(close, 9, 18);


Momentum

Syntax:

momentum(price, length)

Description:

Returns the simple momentum of price over the last length bars.

Example:

plot1 = momentum(close, 10);


Parabolic

Syntax:

parabolic(acclfact)

Description:

Returns Welles Wilder's parabolic stop-and-reverse calculation. AcclFact is the acceleration factor.

Example:

plot1 = parabolic(0.02);


Parablolic2

Syntax:

parabolic2(acclfact, breakout)

Description:

Returns a proprietary stop-and-reverse system inspired by Welles Wilder's parabolic . Acclfact is an acceleration factor, and breakout is a trend breakout length (in bars).

Example:

plot1 = parabolic2(0.02, 3);


RSI

Syntax:

rsi(price,length)

Description:

Welles Wilder's RSI indicator. Price is the data stream to use in the calculation and Length is the lookback period. Note that price doesn't have to be a standard data point, but can be a QScript variable or the result of another function.

Example:

plot1 = rsi(close,14);


SlowD

Syntax:

SlowD(length)

Description:

Stochastic SlowD calculation.

Example:

plot1 = SlowD(14);


SlowK

Syntax:

SlowK(length)

Description:

Stochastic SlowK calculation.

Example:

plot1 = SlowK(14);


SmartMoneyIndex

Syntax:

SmartMoneyIndex(length, smooth, proson)

Description:

Returns the calculation for our proprietary SmartMoneyIndex. Length is the lookback period, smooth is a smoothing factor, and proson determines whether to return the "smart" or "dumb" money indexes. A true value of proson will return the "smart" money.

Example:

plot1 = SmartMoneyIndex(9, 2, true);


StdDev

Syntax:

StdDev(price, length)

Description:

Returns the standard deviation of price over the last length bars.

Example:

plot1 = high + StdDev(close, 20);


Summation

Syntax:

Summation(price, length)

Description:

Returns the value of price summed up over the last length bars.

Example:

plot1 = Summation(high, 10) / Summation(low, 10);


TLSlope

Syntax:

TLSlope(price1, bar1, price2, bar2)

Description:

Returns the slope of the specified trendline. Price1 and Bar1 refer to the leftmost end of the trendline. Price2 and Bar2 refer to the rightmost end. The difference between bar1 and bar2 is what is important, so you don't need to enter exact bar values.

Example:

slope = TLSlope(close[10], barnum-10, close, barnum);

slope = TLSlope(close[10], 10, close, 0); # this is equivalent to the previous example


TLValue

Syntax:

TLValue(price1, bar1, price2, bar2, target)

Description:

Returns a value on the specified trendline. The trendline is set up using price1 and bar1 for the leftmost edge, and price2 and bar2 for the rightmost edge. Then target specifies which bar along the trendline to return a value from. Positive values return past TL values, negative values return future TL values.

Example:

plot1 = TLValue(close[5], 5, close[0], 0, 5);

# this sets up a trendline from the close 5 bars ago to the current close. The value returned is the trendline value 5 bars ago.


TrueHigh

Syntax:

TrueHigh( )

Description:

Returns the true high. The true high is the higher of the high this bar or the close of last bar.

Example:

a = TrueHigh();


TrueLow

Syntax:

TrueLow( )

Description:

Returns the true low. The true low is the lowest of this bar's low or last bar's close.

Example:

a = TrueLow();


TrueRange

Syntax:

TrueRange( )

Description:

Rerturns the difference between the truehigh and the truelow .

Example:

range = TrueRange();


UltraMom

Syntax:

UltraMom(price, length, smooth)

Description:

Returns the value of our proprietary UltraSmooth Momentum curve. Price determines the price series to find the momentum of, length is the number of bars to use in calculating the momentum value, and smooth is a smoothing factor.

Example:

plot1 = UltraMom(close, 10, 4);


Waverage

Syntax:

Waverage(price, length)

Description:

Returns the weighted moving average of price over the last length bars.

Example:

plot1 = waverage(close, 10);


Xaverage

Syntax:

Xaverage(price, length)

Description:

Returns the exponential moving average of price over the last length bars.

Example:

plot1 = Xaverage(close, 10);


Date_to_Bar

Syntax:

Date_to_Bar(year, month, day, time)

Description:

Converts the given date to a bar number . Returns -1 if the date does not refer to a bar on the chart.

Example:

a = Date_to_Bar(1998, 12, 23, 1200);


SavGol

Syntax:

savgol(price, length, poly)

Description:

Returns a smoothed value of price using a modified Savitzky-Golay filter. This is done by fitting a polynomial to the raw input data. Length determines how many bars to use in the fitting process, and poly specifies the order of the polynomial that will be used.

Incidentally, this function is a good example of how to call C/C++ functions from a custom DLL. If you are interested in programming functions in your own DLLs , you ought to take a look at the source code.

Example:

plot1 = savgol(close, 9, 1);


Deleting a QScript

In order to permanently delete a QScript, launch the Script Editor and click "File -> Permanently Delete a Script". The following window will appear:

Simply select the indicator or function you wish to delete, and click "Delete Selected QScript". The compiled QScript, as well as all source code and configuration files will be erased. Once a script has been deleted, there is no way to reverse the operation - so be careful!


Building Drawing Tools

Visual drawing objects like trendlines and retracement levels can also be created using QScript. When setting up a new script , you may set your script up to collect hotspots at startup. Before the script executes, you will be able to click various places on the chart to store the hotspots. Then, once all hotspots are set, your script can access these values to draw various shapes on screen.

For example, if we wanted to create a trendline tool, we could collect 2 hotspots, then connect them with a line. From the user's perspective, this trendline will function identically to the one found under the "Drawing" menu. All drawing cursors will also work on QScripts with hotspots, so the pointing hand, towtruck, wrench, and garbage-can cursors can all be used to interact with our trendline in the expected way.

QScript provides wrappers for Windows graphic functions, so when we create our drawing functions, we are actually directly manipulating the chart bitmap. Access to these functions gives our scripts speed and power, but does require some knowledge of how the underlying functions operate.

Pixels and the Bitmap

The image shown on your computer screen is actually a giant grid of points called a bitmap. A bitmap is made up of many different pixels, each of which has it's own color value. By traversing the bitmap and changing the color of various pixels, we can draw shapes on the screen. Each pixel on this bitmap can be found though it's X and Y coordinates. The X coordinate tells us how far across the bottom of the screen the pixel is, and the Y coordinate tells us how far down the size the pixel is.

The top left corner of the screen is (0,0). As we move to the right, the X pixels increase, and as we move down the screen, the Y pixels increase. So the blue pixel shown on the picture above has an address of (50,25) meaning 50 pixels across and 25 pixels down. Note that this is different from the graphs we all learned in math class since the positive Y direction is down!

Accessing Hotspots

Before our script starts calculating, the user has to set a number of hotspots with the mouse. Once the hotspots are set, we can access them from within our script using the following functions:

hotspot_to_bar: returns what bar the hotspot is on

hotspot_to_price: returns the price level of the hotspot

hotspot_to_pixelx: returns the X pixel value of a hotspot

hotspot_to_pixely: returns the Y pixel value of a hotspot

The first hotspot set on the chart is hotspot 1, the second is hotspot 2, etc. The four functions above give us access to all the information we need about a particular hotspot. For example:

bar1 = hotspot_to_bar(1);

Would place the barnumber of hotspot 1 in our variable "bar1". We could then use the function barnum_to_offset if we needed to access the date or time of this hotspot. The other 3 hotspot functions work similarly. The most important ones from the point of view of the drawing tools goes are hotspot_to_pixelx and hotspot_to_pixely, which respectively give us the X and Y pixel coordinates of the hotspot. The drawing tools discussed below require these pixel locations.

Finding Pixel Locations

You can also use two helper functions to locate important pixel locations:

bar_to_pixel: returns an X pixel location for a given bar.

price_to_pixel: returns a Y pixel location for a given price.

These functions come in handy if you need to adjust your hotspots for some reason. For example, if you require a hotspot to be exactly on the high of a bar, you can get the barnumber via hotspot_to_bar, then pass the high of this bar to the price_to_pixel function to obtain the correct Y pixel value for your drawing tools.

Drawing on the Chart

There is some more terminology to be learned before we begin. The canvas is the drawing area of a particular bitmap. For our purposes, the canvas is our chart. The pen is the tool used to do the drawing. We can't see the pen, but Windows knows where it is and keeps track of it. Just like a real-life artist, Windows can change pens to make lines of different colors and thicknesses.

The following functions can be used to draw on the canvas:

canvas_movepen: moves the pen to a new location

canvas_lineto: draws a line from the current pen location to a new place

canvas_pencolor: changes the color of the pen

canvas_penwidth: changes the width of the pen

canvas_penstyle: changes the style of the pen

canvas_arc: draws an arc using the attributes of the current pen

canvas_ellipse: draws an ellipse using the attributes of the current pen

canvas_rectangle: draws a rectangle using the attributes of the current pen

canvas_text: plots some text at a given location using the attributes of the current font

canvas_textcolor: changes the color of the current font

canvas_textsize: changes the size of the current font

canvas_textwidth: returns the width (in pixels) of the given string if it were to be plotted

canvas_textheight: returns the height (in pixels) of the given string if it were to be plotted

A note about efficiency

Note that QScripts using hotspots are still evaluated in the same way as QScripts without hotspots. Namely, the script is executed on bar 1, all variables are saved, the script is executed on bar 2, the variables are saved again, etc. This happens for all bars until we get to the end of the chart.

This means that if you plot a line on the chart from within a QScript, this line will be plotted on every single bar! Since hotspots do not change with each bar, this is obviously a waste of computer resources. You will notice this extra effort when you try moving or adjusting your QScript with the drawing object cursors.

To avoid this inefficiency, make sure to execute drawing functions only once. This can be accomplished by placing the drawing code in a block like:

if (barnumber==barsback)

{

...drawing code goes here

}

In this case, the drawing code will only execute at the beginning of the script, and never after that time.

An Example

To tie this all together, let's make an example drawing tool. Pretend for a moment that the trendline tool does not exist in the drawing menu, and that we'd like to construct our own in QScript. Let's go to the Script Editor, and create a new script:

We've named our tool "Trendline" and have told it we need it to collect 2 hotspots. These correspond to the end points of the trendline. Notice that we've got the scaling set to "price". This will keep Wave59 from creating a subgraph for the indicator when loaded on an automatically scaled chart.

Here's the code for our trendline tool. The red numbers at the side are not actually entered, but are there to make it simpler to discuss what's happening in this script.

1 input: color(green);

2

3 if (barnumber==barsback)

4 {

5      #set the pen color to the correct value

6      canvas_pencolor(color);

7

8      #get pixel values of first hotspot

9      x=hotspot_to_pixelx(1);

10      y=hotspot_to_pixely(1);

11

12      #move the pen to the first point

13      canvas_movepen(x,y);

14

15      #get pixel values of the second hotspot

16      x=hotspot_to_pixelx(2);

17      y=hotspot_to_pixely(2);

18

19      #draw a line to the second hotspot

20      canvas_lineto(x,y);

21 }

line 1: We set up an input "color". This will allow us to change the color of our trendline.

line 3: We only want to execute this drawing code once, and not on every single bar. Don't forget that QScripts are evaluated once on every bar! This is an important speed consideration.

line 6: We set the color of the current pen. The pen will remain this color until we change it again.

lines 9-10: We get the X and Y pixel values of our first hotspot. This is the beginning of our trendline. The very first hotspot on a chart is always hotspot "1".

line 13: We place the pen at our first hotspot.

lines 15-16: We get the X and Y pixel values of the second hotspot. This is the end of our trendline.

line 20: We draw a line to our new x and y values and complete the trendline. Since the pen was positioned at the first hotspot back at line 13, this will connect our two hotspots.

Please try this script yourself and verify that it works as described. This is a very powerful feature of QScript, and will allow you to use drawing tools in your trading that didn't ship with Wave59.


Hotspot_to_Bar

Syntax:

hotspot_to_bar(hotspot number)

Description:

Returns the bar value of a given hotspot. The first hotspot on a chart is 1. You can convert the barvalue to an offset in order to get data values by using the function barnum_to_offset .

Example:

bar2 = hotspot_to_bar(2);


Hotspot_to_Price

Syntax:

hotspot_to_price(hotspot number)

Description:

Returns the price value of a given hotspot. The first hotspot on a chart is 1.

Example:

price2 = hotspot_to_price(2);


Hotspot_to_PixelX

Syntax:

hotspot_to_pixelx(hotspot number)

Description:

Returns the X pixel (horizontal) coordinate of the given hotspot.

Example:

x = hotspot_to_pixelx(2);


Hotspot_to_PixelY

Syntax:

hotspot_to_pixely(hotspot number)

Description:

Returns the Y pixel (vertical) coordinate of the given hotspot.

Example:

y = hotspot_to_pixely(2);


Canvas_MovePen

Syntax:

canvas_movepen(x pixel, y pixel)

Description:

Moves the pen to the given x and y pixel coordinates on the canvas. Does not draw any lines.

Example:

canvas_movepen(45, 67);


Canvas_LineTo

Syntax:

canvas_movepen(x pixel, y pixel)

Description:

Draws a line from the current pen position to the coordinates given in the function call using the attributes of the current pen. Also moves the pen to the new location.

Example:

canvas_lineto(45, 67);


Canvas_PenColor

Syntax:

canvas_pencolor(color)

Description:

Changes the color of the pen.

Example:

canvas_pencolor(red);


Canvas_PenWidth

Syntax:

canvas_penwidth(width)

Description:

Changes the width of the pen (in pixels).

Example:

canvas_penwidth(3); # the pen draws lines 3 pixels thick from now on


Canvas_PenStyle

Syntax:

canvas_penstyle(style)

Description:

Changes the style of the pen.

Example:

canvas_penstyle(ps_dot); # draws dotted lines now until we change it back


Canvas_Arc

Syntax:

canvas_arc(x1, y1, x2, y2, x3, y3, x4, y4)

Description:

Use canvas_arc to draw an elliptically curved line with the current pen. The arc traverses the perimeter of an ellipse that is bounded by the points (x1,y1) and (x2,y2). The arc is drawn following the perimeter of the ellipse, counterclockwise, from the starting point to the ending point. The starting point is defined by the intersection of the ellipse and a line defined by the center of the ellipse and (x3,y3). The ending point is defined by the intersection of the ellipse and a line defined by the center of the ellipse and (x4, y4).

Note: On Windows 95, the sums X1 + X2 and Y1 + Y2 cannot exceed 32768. Also, the sum X1 + X2 + Y1 + Y2 cannot exceed 32768

Example:

canvas_arc(50, 50, 200, 200, 50, 60, 180, 180);


Canvas_Ellipse

Syntax:

canvas_ellipse(x1, y1, x2, y2)

Description:

Draws an ellipse on the canvas using the current pen. The ellipse is bounded by the rectangle with the upper left-hand corner at (x1, y1) and lower right-hand corner at (x2, y2).

Example:

canvas_ellipse(50, 50, 200, 200);


Canvas_Rectangle

Syntax:

canvas_rectangle(x1, y1, x2, y2)

Description:

Draws a rectangle on the canvas with the current pen. The rectangle is defined with upper left corner at (x1, y1) and lower right corner at (x2, y2).

Example:

canvas_rectangle(45, 45, 110, 120);


Canvas_Text

Syntax:

canvas_text(x, y, text)

Description:

Writes a string on the canvas, starting at the point (x,y) (for the upper left-hand corner of the text), and then updates the pen position to the end of the string.

Example:

canvas_text(10, 10, "hi there!");


Canvas_TextColor

Syntax:

canvas_textcolor(color)

Description:

Changes the color of the canvas text. All text drawn using canvas_text( ) will remain this color until it is changed again.

Example:

canvas_textcolor(red);


Canvas_TextSize

Syntax:

canvas_textsize(size)

Description:

Changes the size of the canvas text. All text drawn using canvas_text( ) will remain this size until it is changed again.

Example:

canvas_textsize(18); # an 18 point text size gives us big letters!


Canvas_TextWidth

Syntax:

canvas_textwidth(text)

Description:

Returns the width (in pixels) of the given text if it had been drawn on the screen with the current font attributes. This is useful for positioning and centering text.

Example:

width = canvas_textwidth("how many pixels wide am I?");


Canvas_TextHeight

Syntax:

canvas_textheight(text)

Description:

Returns the height (in pixels) of the given text if it had been drawn on the screen with the current font attributes. This is useful for positioning and centering text.

Example:

height = canvas_textheight("how many pixels tall am I?");


Predict

Syntax:

predict(x, y, z, pred, lkbk, ahead)

Description:

This function uses an adaptive algorithm to forecast the value of "pred". Unlike other artificial intelligence techniques like neural nets, the prediction engine behind this function is so fast that all internal weights and settings can be retrained on a bar-by-bar basis. Parameters "x", "y", and "z" are three inputs that will be used to forecast the value of "pred". The prediction is for "ahead" bars into the future. "Lkbk" determines how many bars of history are used during training.

Example:

# calculate the inputs

x = ultramom(close, 10, 4);

y = ultramom(close, 12, 4);

z = ultramom(close, 14, 4);

# predict the value of "x" 2 bars into the future, using a 50 bar window to train with

output = predict(x, y, z, x, 50, 2);


PercentR

Syntax:

percentr(length)

Description:

This function returns Larry Williams' Percent R oscillator.

Example:

# plot a 14 bar PercentR curve

plot1 = percentr(14);


IFF

Syntax:

iff(condition, trueval, falseval)

Description:

If condition is true, returns trueval. Otherwise, returns falseval. This is a speedy way of abbreviating a short if...else statement.

Example:

a = iff( true, 1, -1); # a holds the value 1 since the first parameter is true

b = iff( high>high[1], open, close);

# if this bar's high is greater than last bar's high, b holds the value of the open. If not, b holds the value of the close.


Execute

Syntax:

execute(program, parameter1, parameter2, ...., parameterN)

Description:

This function executes an external program. The program name parameter is followed by an optional list of command line inputs. If the command was executed, this function will return true. If the command could not be executed, a false value will be returned.

Example:

a = execute("notepad","myfile.txt"); # this will launch notepad.exe and will cause it to load up myfile.txt


Astro_Declination

Syntax:

astro_declination(year, month, day, time, planet, geocentric)

Description:

Returns declination data for an astrological body at the given time. Year, month, day, and time specify the instant we are interested in. Note that time is local time for your computer. Planet is one of the following constants, which will determine which body we are interested in:

planets:

astro_mercury

astro_venus

astro_earth

astro_moon

astro_sun

astro_mars

astro_jupiter

astro_saturn

astro_uranus

astro_neptune

astro_pluto

asteroids:

astro_ceres

astro_chiron

astro_juno

astro_pallas

astro_pholus

astro_vesta

Geocentric is either true or false. If true, geocentric (earth-centered) positions will be returned. Otherwise heliocentric (sun-centered) positions will be returned.

Example:

print astro_declination(1998, 1, 1, 1200, astro_moon, true); # prints -12.69 (mountain time)


Astro_DeclinationUT

Syntax:

astro_declinationUT(year, month, day, time, planet, geocentric)

Description:

Returns declination data for an astrological body at the given time. Year, month, day, and time specify the instant we are interested in. Note that time is Universal Time (Greenwich). Planet is one of the following constants, which will determine which body we are interested in:

planets:

astro_mercury

astro_venus

astro_earth

astro_moon

astro_sun

astro_mars

astro_jupiter

astro_saturn

astro_uranus

astro_neptune

astro_pluto

asteroids:

astro_ceres

astro_chiron

astro_juno

astro_pallas

astro_pholus

astro_vesta

Geocentric is either true or false. If true, geocentric (earth-centered) positions will be returned. Otherwise heliocentric (sun-centered) positions will be returned.

Example:

print astro_declinationUT(1998, 1, 1, 1200, astro_moon, true); # prints -13.65 (mountain time)


PFE

Syntax:

pfe(length)

Description:

This function calculates the value of Al Larson's Polarized Fractal Efficiency curve. This measures how much price "wanders" when moving from point A to point B. The result is an overbought/oversold indicator similar to RSI or Stochastics.

Example:

# returns the pfe calculation with a 14 bar lookback

value1 = pfe(14);


Bar_to_Pixel

Syntax:

bar_to_pixel(barnumber)

Description:

Returns the x-pixel screen location location of the given bar. Returns -1 if offscreen. Useful for custom drawing tools .

Example:

x_pixel = bar_to_pixel(barum); # returns the pixel location of the current bar


Price_to_Pixel

Syntax:

price_to_pixel(price)

Description:

Returns the y-pixel screen location of the given price. Returns -1 if off screen. Useful for custom drawing tools .

Example:

y_pixel = price_to_pixel(578.50); # returns pixel location on screen for this price


JulianDay

Syntax:

julianday(year, month, day, time)

Description:

JulianDay will return the julian day value on the given date. Enter time as local time. To reverse the function, use julian_to_year , julian_to_month , julian_to_day , and julian_to_time .

Example:

jd=julianday(year[1], month[1], day[1], time[1]); # calculates julian day value on the previous bar


Astro_Location

Syntax:

astro_location(year, month, day, time, latitude, longitude, type, use_tropical)

Description:

Returns astronomical information (ascendant, midheaven, or vertex) based on a particular geographical location. Year, month, day, and time specify the instant we are interested in. Note that time is local time for your computer. Latitude and Longitude specify the location on Earth we are interested in looking at.

For reference, here are the locations of the two major US exchanges:

New York:

latitude = 40.7056

longitude = 74.008

Chicago:

latitude = 41.8868

longitude = 87.6386

Type is one of the following constants, which will determine which value we are interested in:

astro_ascendant

astro_midheaven

astro_vertex

astro_eastpoint

Use_Tropical is either true or false. If true, the tropical (western style) zodiacal positions will be returned. Otherwise sidereal positions will be returned.

Example:

print astro_location(1998, 1, 1, 1200, 40.7, 74.0, astro_ascendant, true); # prints new york ascendant


Astro_LocationUT

Syntax:

astro_locationUT(year, month, day, time, latitude, longitude, type, use_tropical)

Description:

Returns astronomical information (ascendant, midheaven, or vertex) based on a particular geographical location. Year, month, day, and time specify the instant we are interested in. Note that time is Universal Time (Greenwich). Latitude and Longitude specify the location on Earth we are interested in looking at.

For reference, here are the locations of the two major US exchanges:

New York:

latitude = 40.7056

longitude = 74.008

Chicago:

latitude = 41.8868

longitude = 87.6386

Type is one of the following constants, which will determine which value we are interested in:

astro_ascendant

astro_midheaven

astro_vertex

astro_eastpoint

Use_Tropical is either true or false. If true, the tropical (western style) zodiacal positions will be returned. Otherwise sidereal positions will be returned.

Example:

print astro_location(1998, 1, 1, 1200, 40.7, 74.0, astro_ascendant, true); # prints new york ascendant


NineFive

Syntax:

ninefive( )

Description:

This function reuturns the current 9-5 Count indication as a string . Blue numbers are positive, and red numbers are negative. Gold count values are returned in the range 11 to 15 to differentiate them from the blue/red numbers. Note that 8's and 14's may have asterisks appended to the end, to indicate early trigger signals. If there is no new count on the current bar, the function returns an empty string.

To keep things clear, here are the return values for signal numbers:

bullish signals:

Blue 9 = "9"

Blue 8* = "8*"

Gold 5 = "15"

Gold 4* = "14*"

bearish signals:

Red 9 = "-9"

Red 8* = "-8*"

Gold 5 = "-15"

Gold 4* = "-14*"

For more information on this indicator, please see Wave59 Help.

Example:

# returns the current 9-5 Count

value1 = ninefive( );


Mousedown

Syntax:

mousedown

Description:

Returns true if the left mouse button is held down, false if it is not. This can be useful for scripts that are computationally intensive and require hotspot detection. Rather than recalculating the script as it is being moved (by dragging with the hotspot), we can short circuit it and only compute once the mouse has been released.

Example:

if (mousedown == true) {

print "mouse is pressed"; # this will print if the button is held down

}


Lomb_Periodogram

Syntax:

lomb_periodogram(&price,length,oversample,return_type)

Description:

This is a master function that returns all values related to the Lomb Periodogram. Note that the price value must be a reference variable . The return_type can be one of three possible values:

1 = phase angle

2 = probability of error

3 = dominant cycle length

For ease of use, please use Lomb_Phase , Lomb_Probability , and Lomb_Cycle instead of this function.

Example:

price=close;

phase = lomb_periodogram(&price,25,10,1);


Lomb_Phase

Syntax:

lomb_phase(price,length,oversample)

Description:

This function returns the phase angle as found by the Lomb Periodogram. Price refers to the data series to examine, length refers to the lookback period over which to compute the return value, and oversample is an internal parameter governing how the data is sampled. The default value for oversample is 10.

Example:

phase=lomb_phase(close,25,10);


Lomb_Probability

Syntax:

lomb_probability(price,length,oversample)

Description:

This function returns the probability of error as found by the Lomb Periodogram. A low probability means a significant periodic cycle has been detected in the data. A high probability means the algorithm had difficulty in detecting a stable cycle, and that all results from the calculation should be treated with caution. Price refers to the data series to examine, length refers to the lookback period over which to compute the return value, and oversample is an internal parameter governing how the data is sampled. The default value for oversample is 10.

Example:

value1=lomb_probability(close,25,10);


Lomb_Cycle

Syntax:

lomb_cycle(price,length,oversample)

Description:

This function returns the dominant cycle length (in bars) as found by the Lomb Periodogram. Price refers to the data series to examine, length refers to the lookback period over which to compute the return value, and oversample is an internal parameter governing how the data is sampled. The default value for oversample is 10.

Example:

cycle_len=lomb_cycle(close,25,10);


Price_to_SQ9

Syntax:

price_to_sq9(price, centernum)

Description:

Returns the degree value of the number when plotted on the square of nine. Assumes that the square moves counter clockwise and that 0 degrees is to the right.

Example:

degree = price_to_sq9(28, 1); # returns 0, on a square with center = 1


Price_to_NumSq

Syntax:

price_to_numsq(price, center_num, sides)

Description:

Returns the degree value of the number when plotted on a numbered square with sides equal to sides. For example, if sides was 6, the hexagon chart would be used. If sides were 8, an octogon chart would be used. Assumes that the square moves counter clockwise and that 0 degrees is to the right.

Example:

degree = price_to_numsq(1000, 0, 7); # returns the degree value of 1000 when plotted on a 7 sided chart


Julian_to_Year

Syntax:

julian_to_year(jd)

Description:

Returns the year corresponding to the given julianday value.

Example:

jd=julianday(2005,12,3,1239);

yr=julian_to_year(jd) # returns 2005


Julian_to_Month

Syntax:

julian_to_month(jd)

Description:

Returns the month corresponding to the given julianday value.

Example:

jd=julianday(2005,12,3,1239);

mn=julian_to_month(jd) # returns 12


Julian_to_Day

Syntax:

julian_to_day(jd)

Description:

Returns the day corresponding to the given julianday value.

Example:

jd=julianday(2005,12,3,1239);

dy=julian_to_day(jd) # returns 3


Julian_to_Time

Syntax:

julian_to_time(jd)

Description:

Returns the time corresponding to the given julianday value.

Example:

jd=julianday(2005,12,3,1239);

tm=julian_to_time(jd) # returns 1239


Alert

Syntax:

alert(message, sound)

Description:

This function will issue an alert when called. A message box will pop up with a user defined note, and a sound will play. This will only happen on the most recent bar on the chart - no historical alerts will be issued. The message parameter is a string that defines what notice should be written to the alert box. If blank, no alert box will appear, but a sound will still play. The sound parameter determines which WAV file in the sounds folder the alert will activate. The sounds folder is located in the Wave59 installation directory, usually c:\program files\wave59 rt\sounds. To play a custom WAV files, please make sure they are located in this directory. Pass in an empty string to the sound parameter just to write the message without any accompanying sound.

The following sounds have been installed to the sounds directory by using the initial setup file (version 2.5 and later) found at wave59.com - member login - download - step 2:

  • boing.wav
  • cuckoo.wav
  • dingdong.wav
  • harp.wav
  • horn.wav
  • knock.wav
  • phone1.wav
  • phone2.wav

Example:

alert("123","phone1.wav"); # writes the message 123 to an alert box, and plays the wav file phone1.wav

alert("","cuckoo.wav"); # no alert message pops up, but cuckoo.wav still plays


Astro_RiseSet

Syntax:

astro_riseset(year, month, day, time, latitude, longitude, planet, return_type)

Description:

Returns the rising time, setting time, transit time (overhead), and itransit time (underneath) for a particular planet at a given geographic location on Earth. The time is returned in local time.

possible planet values:

astro_mercury

astro_venus

astro_moon

astro_sun

astro_mars

astro_jupiter

astro_saturn

astro_uranus

astro_neptune

astro_pluto

astro_true_node

return types:

astro_rise

astro_set

astro_transit

astro_itransit

Latitude and Longitude are used to specify the geographical location of the point on the Earth we are interested in. For reference, here are the locations of the two major US exchanges:

New York:

latitude = 40.7056

longitude = 74.008

Chicago:

latitude = 41.8868

longitude = 87.6386

Note that this function is computationally intensive. For maximum performance, it is best to set it up inside a block that only triggers once per day, then save the result in a variable for use later in the script. The example below shows how this can be accomplished.

Example:

if (day != day[1]) # this block will only trigger at first bar of the day

{

# returns the rising time of the sun in New York for the given day

risetime = astro_riseset(year, month, day, time, 40.7, 74.0, astro_sun, astro_rise);

}


Cusp_Declination

Syntax:

cusp_declination(year, month, day, time, degree)

Description:

This function returns the declination of the ascendant, midheaven, or any of the house cusps. The equatorial longitude of the item to find the declination for must be calculated before calling this function, and then passed in as the degree parameter.

Example:

ascendant = astro_location(1998, 1, 1, 1200, 40.7, 74.0, astro_ascendant, true); # calc asc first

asceendant_declination = cusp_declination(1998, 1, 1, 1200, ascendant); # = asc declination


Cusp_DeclinationUT

Syntax:

cusp_declinationUT(year, month, day, time, degree)

Description:

This function returns the declination of the ascendant, midheaven, or any of the house cusps. The equatorial longitude of the item to find the declination for must be calculated before calling this function, and then passed in as the degree parameter. Note that time is Universal Time (Greenwich), and not local time on your computer as would be the case with cusp_declination .

Example:

ascendant = astro_location(1998, 1, 1, 1200, 40.7, 74.0, astro_ascendant, true); # calc asc first

asceendant_declination = cusp_declinationUT(1998, 1, 1, 1200, ascendant); # = asc declination


NatalForecast

Syntax:

natalforecast(JD, NJD, harmonic, xharmonic, lat, lon, influences)

Description:

This function returns the value of the Natal Forecast (see Wave59 help for a description of this indicator) for a given moment in time. The parameter list is as follows.

JD: The moment in time, represented as a Julian Day , for which the calculation is to be made. Use the JulianDay function to calculate this value.

NJD: The natal date, or first trade date, also represented as a Julian Day .

Harmonic: The planetary harmonic to use in the calculation.

XHarmonic: The exchange harmonic to use in the calculation.

Lat: The geographical latitude of the place where the calculation is to be made for.

Lon: The geographical longitude of the place where the calculation is to be made for.

For reference, here are the locations of the two major US exchanges:

New York:

latitude = 40.7056

longitude = 74.008

Chicago:

latitude = 41.8868

longitude = 87.6386

Influences: A 17 element string, made up of 1's and 0's, that determines which planets go into the calculation. A "1" means to use the planet represented by the position in the string, and a "0" means do not use it. For example, a string like "11111111110000000" would mean use the first 10 planets, but not the next 7. Each position in the string refers to a particular planetary body, as follows:

Element in String Planetary Body

1 Mercury

2 Venus

3 Sun

4 Mars

5 Jupiter

6 Saturn

7 Uranus

8 Neptune

9 Pluto

10 Moon

11 North Node

12 Chiron <---Asteroids here and below

13 Pholus

14 Ceres

15 Pallas

16 Juno

17 Vesta

As another example, if we just wanted to use Mercury and Venus in our calculations and no other bodies, we would need to pass an influence string into the function that looked like this: "11000000000000000".

Example:

# this will calculate the natalforecast using harmonics of 36/6, for New York,

# and using all planets available, including the asteroids

natal_date = julianday(1982, 4, 21, 930); # use birth of SP as natal date

today_date = julianday(year, month, day, time); # this is the current bar's JD

natal = natalforecast(today_date, natal_date, 36, 6, 40.7056, 74.008, "11111111111111111");


History59_Start

Syntax:

history59_start( )

Description:

This function restarts the History59 data collector after a call to history59_stop . History59 will manage it's own connection to the data feed, so this function is only necessary if for some reason you wish to override normal program operation.

Example:

if (barnum == 45)

history59_stop( ); # stops data collection at bar 45

if (barnum == 46)

history59_start( ); # restarts data collection the next bar


History59_Stop

Syntax:

history59_stop( )

Description:

This function stops the History59 data collector. After a call to this function, the data collector will remain idle and will not collect any incoming data until it is either restarted or receives a call from history59_start . History59 will manage it's own connection to the data feed, so this function is only necessary if for some reason you wish to override normal program operation.

Example:

if (barnum == 45)

history59_stop( ); # stops data collection at bar 45

if (barnum == 46)

history59_start( ); # restarts data collection the next bar


Last_Bar_On_Chart

Syntax:

last_bar_on_chart

Description:

This keyword returns the number of the bar number of the farthest right edge of the chart. Note that this bar location will usually correspond with a time in the future and will therefore likely not have any data associated with it. To get the bar number of the last actual price bar on the chart, please use updating_bar instead.

Example:

text(last_bar_on_chart, close, "A", tx_center, 8); # will plot an A at the farthest right side of the chart


Recalculate_All

Syntax:

recalculate_all( )

Description:

This function allows you to call the Options - Recalculate All feature from within a script. When called, Wave59 will purge the chart and built it again from scratch, first issuing a historical data request to your data feed, reloading all indicators, and recalculating everything as if you had just opened the chart. In order to prevent Wave59 from getting locked in an infinite loop of recalculate requests, the script engine will not allow this function to be run more than one time every three seconds. To get around that limitation, please see the Sleep function for a workaround. Note that this is a specialized and potentially very time consuming function, and most users will never need to implement it. If you do happen to be one of the users who finds it useful, make sure to issue calls as infrequently as possible. Currenttime and currentseconds may be helpful if you need to create a time constraint within your script to limit the number of calls issued.

Example:

if (barnum == 108)

Recalculate_All( ); # the chart will be recalculated when bar 108 arrives


ScreenCapture

Syntax:

ScreenCapture(filename)

Description:

This function allows you to save the screen as a JPEG or PNG image. It performs the same task as if you had clicked Options - Screen Capture - Send to File.

Example:

if (barnum==barsback) {

ScreenCapture("c:\myscreen.jpg"); # the screen is saved as a jpeg image

}


Last_Bar_on_Chart

Syntax:

last_bar_on_chart

Description:

Returns the bar number of the last bar available on the chart. This is the bar number at which point the data will end unless more history is added to the database via format - chart - database, etc.

Example:

ref=trendline(barnum,close,last_plot_bar,close,red); # draws a trendline to the end of the chart


barsback

Syntax:

barsback

Description:

Returns the bar number when the script actually starts executing. All scripts must wait until enough history has passed to allow all offsets to be filled with valid information. For example, at least 10 bars of history must be present on the chart before a call to close[10] would return a meaningful result. Barsback returns the reference bars setting that governs how much history is stored before execution begins.

Example:

if (barnumber == barsback) {

# this will execute on the very first bar the QScript runs

}


BarsSinceEntry

Syntax:

barssinceentry

Description:

Returns the number of bars that have passed since a trading system entered a position.

Example:

if (marketposition==1) and (barssinceentry>5) {

exitlong(0,close,"market","onebar"); # this will exit a long position if 5 bars have passed since entry

}


Buy

Syntax:

buy(quantity, price, order_type, order_expiration)

Description:

This is used to enter a buy order during system testing. The parameters involved are:

quantity: (numeric) the number of shares/contracts to enter the order for

price: (numeric) the price at which to place the order

order_type: (string) either "stop", "limit", "market", or "nextopen" which specifies what kind of order to place.

order_expiration: (string) either "gtc", "day", or "onebar". A "onebar" order will only be active on the very next bar.

Wave59 will allow you to place as many orders in the same direction as you desire, so if you only want to be long or short one contract at a time, you will need to check the system's status using the marketposition keyword.

Note that all parameters are required, although they might all not be used. For example, price or order_expiration is not important for a market order, but the QScript engine will still expect to see a value there.

This function returns a unique reference number which can be used to cancel the order later on with the CancelOrder(ref) function. That process is only necessary when using "gtc" order_expiration values which remain active indefinitely.

Example:

if (marketposition <= 0) {

ref=buy(1,close,"market","onebar"); # this will enter an order to buy on the close if the system is not currently long

}

# this enters an order to buy one contract at the low of the bar or better, and the order will remain in effect until canceled

ref=buy(1, low, "limit", "gtc");

# this enters an order to buy 10 contracts at 1500.50 on a stop, and will only be active for the very next bar on the chart

ref=buy(10, 1500.50, "stop", "onebar");


MarketPosition

Syntax:

marketposition

Description:

Returns the number of shares or contracts a system is long or short. Long positions will be denoted by positive values, short positions will be denoted by negative values, and a value of zero means the system is currently flat.

Example:

if (marketposition==0) {

buy(0,close,"market","onebar"); # this will enter a long position if the system is currently flat

}


CancelAll

Syntax:

cancelall( )

Description:

This will cancel all active orders on the chart.

Example:

cancelall( );


CancelOrder

Syntax:

cancelorder(orderid)

Description:

This function cancels the order with the given orderid. The function returns true if the order was canceled, and false otherwise (if the order doesn't exist, or a bad order number has been passed).

Example:

ref = buy(1,close+10,"stop","gtc"); # places an order

cancelorder(ref); # cancels it


EntryPrice

Syntax:

entryprice

Description:

Returns the entryprice of the last opened trade, or -1 if no trades have been placed.

Example:

if (nextopen > entryprice)

exitlong(0,close,"nextopen","onebar"); # this will exit a long position at the next profitable open


EquityCurve

Syntax:

equitycurve

Description:

Returns the value of the system equity curve. The value is in points generated since the beginning of the chart, coming into the current bar.

Examples:

plot1 = equitycurve; # plots the number of points earned coming into the current bar

plot2 = equitycurve[2]; # plots the number of points earned coming into the bar two bars ago


ExitLong

Syntax:

exitlong(quantity, price, order_type, order_expiration)

Description:

This is used to exit from a long position during system testing. The parameters involved are:

quantity: (numeric) the number of shares/contracts to enter the order for. If less than or equal to zero, the entire position will be exited.

price: (numeric) the price at which to place the order

order_type: (string) either "stop", "limit", "market", or "nextopen" which specifies what kind of order to place.

order_expiration: (string) either "gtc", "day", or "onebar". A "onebar" order will only be active on the very next bar.

This function will only execute if the system is currently long. It will have no effect otherwise. Note that a quantity less than or equal to zero will result in all long positions, no matter what the quantity, to be exited. Also note that all parameters are required, although they might all not be used. For example, price or order_expiration is not important for a market order, but the QScript engine will still expect to see a value there.

This function returns a unique reference number corresponding to the order id of the trade. This value is currently not used in QScript, but is provided for future use with autotrading and reporting.

Example:

buy(4,close,"market","onebar"); # buys 4 contracts at the close

if (nextopen > entryprice)

exitlong(1,nextopen,"nextopen","onebar"); # exits one contract on the first profitable open

exitlong(0,entryprice+3,"limit","onebar"); # exits entire open position at a profit of 3 points


ExitShort

Syntax:

exitshort(quantity, price, order_type, order_expiration)

Description:

This is used to exit from a short position during system testing. The parameters involved are:

quantity: (numeric) the number of shares/contracts to enter the order for. If less than or equal to zero, the entire position will be exited.

price: (numeric) the price at which to place the order

order_type: (string) either "stop", "limit", "market", or "nextopen" which specifies what kind of order to place.

order_expiration: (string) either "gtc", "day", or "onebar". A "onebar" order will only be active on the very next bar.

This function will only execute if the system is currently short. It will have no effect otherwise. Note that a quantity less than or equal to zero will result in all short positions, no matter what the quantity, to be exited. Also note that all parameters are required, although they might all not be used. For example, price or order_expiration is not important for a market order, but the QScript engine will still expect to see a value there.

This function returns a unique reference number corresponding to the order id of the trade. This value is currently not used in QScript, but is provided for future use with autotrading and reporting.

Example:

sell(4,close,"market","onebar"); # sells 4 contracts at the close

if (nextopen < entryprice)

exitshort(1,nextopen,"nextopen","onebar"); # exits one contract on the first profitable open

exitshort(0,entryprice+5,"stop","onebar"); # exits entire open position at a 5 point stop


NextOpen

Syntax:

nextopen

Description:

Returns the next bar's opening price. Be aware that this information is not available in real life on the previous bar, but is made available one bar early due to the architecture of the QScript engine. Needless to say, mixing exits on the close of the current bar based on values of the next open will produce a very appealing, yet imaginary, system report!

Example:

if (nextopen > entryprice)

exitlong(0,close,"nextopen","onebar"); # this will exit a long position at the next profitable open


NumTrades

Syntax:

numtrades

Description:

Returns the number of trades entered so far on the chart, not including any exits.

Example:

print("number of trades: ",numtrades); # sends the number of trades taken to the print log


OpenEquity

Syntax:

openequity

Description:

Returns the number of points that would be made or lost by the current open position if it was exited on the close of the bar. Flat positions will result in a value of zero.

Example:

if (openequity>0)

exitlong(0,close,"market","onebar"); # this will exit a long position on the close if the trade is profitable


Sell

Syntax:

sell(quantity, price, order_type, order_expiration)

Description:

This is used to enter a sell order during system testing. The parameters involved are:

quantity: (numeric) the number of shares/contracts to enter the order for

price: (numeric) the price at which to place the order

order_type: (string) either "stop", "limit", "market", or "nextopen" which specifies what kind of order to place.

order_expiration: (string) either "gtc", "day", or "onebar". A "onebar" order will only be active on the very next bar.

Wave59 will allow you to place as many orders in the same direction as you desire, so if you only want to be long or short one contract at a time, you will need to check the system's status using the marketposition keyword.

Note that all parameters are required, although they might all not be used. For example, price or order_expiration is not important for a market order, but the QScript engine will still expect to see a value there.

This function returns a unique reference number which can be used to cancel the order later on with the CancelOrder(ref) function. That process is only necessary when using "gtc" order_expiration values which remain active indefinitely.

Example:

if (marketposition >= 0) {

ref=sell(1,close,"market","onebar"); # this will enter an order to sell on the close if the system is not currently short

}

# this enters an order to sell one contract at the high of the bar or better, and the order will remain in effect until canceled

ref=sell(1, high, "limit", "gtc");

# this enters an order to sell 10 contracts at 1500.50 on a stop, and will only be active for the very next bar on the chart

ref=sell(10, 1500.50, "stop", "onebar");


TradeResult

Syntax:

traderesult[trades_ago]

Description:

Returns the result of previous closed trades. Traderesult[0] would return the value of the most recently closed trade, and traderesult[1] would return the value of the trade closed before that one. If the trades_ago offset is larger than the number of trades entered thus far (see numtrades ), QScript will simply return a value of zero.

Example:

if (traderesult > 0) qty=2; # if the last trade was profitable, enter 2 contracts on the next order

else qty=1; # otherwise, just enter one contract

buy(qty,close,"nextopen","onebar");


SetOCOTag

Syntax:

setocotag(orderid, tag)

Description:

This function allows you to create linked OCO ("Order Cancels Order") orders. When one order in an OCO group is filled, all other orders in that group will be canceled. Note that canceling one order in an OCO group will result in canceling all other orders as well. OrderID is the id number returned when the order was placed with functions like Buy or Sell , and Tag is a string variable that QScript will use to identify an OCO group. If you are managing multiple OCO groups at once, make sure each one has a unique Tag variable.

Example:

# This system will buy the high or sell the low of the current bar, whichever comes first

id1 = buy(1,high,"stop","onebar"); # set up the buy and sell orders

id2 = sell(1,low,"stop","onebar");

# Use the current barnumber as the ocotag for simplicity. We could also use "ooga booga" or any other valid string here

ocotag = to_string(barnum);

setocotag(id1,ocotag); # Place the buy order into the oco group

setocotag(id2,ocotag); # Place the sell order into the oco group


WasOrderFilled

Syntax:

wasorderfilled(orderid)

Description:

Use this function to determine if a particular order was filled. If the order referenced by the OrderId parameter was filled, this function returns true, otherwise it returns false.

Example:

if (barnum == 250)

ref = buy(1,high,"stop","gtc"); # set up a good-until-canceled order on bar number 250

if (wasorderfilled(ref)==true) # when the buy order gets filled, enter a protective stop

ref = exitlong(1,low,"stop","gtc");


FillAction

Syntax:

fillaction(orderid)

Description:

Use this function to determine whether a particular filled order was a buy(1), sell(-1), exitlong(-2), or exitshort(2) order. OrderId is the return value from when the order was placed using functions such as Buy or Sell . The function will return 0 if OrderId does not correspond to any filled orders.

Example:

ref = buy(1,high,"stop","gtc"); # set up a good-until-canceled order

action = fillaction(ref); # action will be a 1 (=buy order) assuming the order was filled


FillPrice

Syntax:

fillprice(orderid)

Description:

Use this function to determine at what price a particular order was filled. OrderId is the return value from when the order was placed using functions such as Buy or Sell . The function will return -1 if OrderId does not correspond to any filled orders.

Example:

ref = buy(1,1500,"stop","gtc"); # set up a good-until-canceled order

price = fillprice(ref); # assuming the order was filled, this will return 1500


FillBar

Syntax:

fillbar(orderid)

Description:

Use this function to determine the bar number a particular order was filled on. OrderId is the return value from when the order was placed using functions such as Buy or Sell . The function will return -1 if OrderId does not correspond to any filled orders.

Example:

ref = buy(1,1500,"stop","gtc"); # set up a good-until-canceled order

mybar = fillbar(ref); # assuming the order was filled, this will return the barnumber when the fill occurred


FillQty

Syntax:

fillqty(orderid)

Description:

Use this function to determine how many shares or contracts were filled on a particular order. Any extra shares required to reverse an open position will be included in the return value. OrderId is the return value from when the order was placed using functions such as Buy or Sell . The function will return -1 if OrderId does not correspond to any filled orders.

Example:

ref1 = sell(1,close,"market","onebar"); # enter a short

ref2 = buy(1,close,"market","onebar"); # reverse the short to long

qty1 = fillqty(ref1); # this will return a value of 1

qty2 = fillqty(ref2); # this will return a value of 2, one share to reverse the short, and the other to enter a new long


IB_PlaceOrder

Syntax:

IB_PlaceOrder(buysell, qty, price, type, tif, ocagroup)

Description:

Use this function to place an order through Interactive Brokers. This order requires that Wave59 be using Interactive Brokers with order entry as the data feed. The order will be placed in exactly the same way as if you were trading off the chart using the manual order placement tools. Once placed, the order will return a unique order number which can be used to cancel or check the status of the order later. Note that Wave59 will not allow orders to be placed on any bar except the most recent. Also note that this function will not place any orders if the script is being debugged.

The following parameters are required:

buysell: can be "buy", "sell" , or "short".

qty: the quantity to buy or sell.

price: the price to buy or sell at (ignored for market orders).

type: the order type. Can be "stop", "limit", or "market".

tif: time in force, either "day" or "gtc".

ocagroup: use this to create order-cancels-order groups. Each group needs a unique identifying string. When one order is completed in the group, all other orders will be canceled. Enter an empty string ("") if you do not wish to use this feature.

It is highly recommended that all mechanical systems using this function be tested using Interactive Brokers' paper trading account option, which is a free service available to all account holders. IB will issue a special username/password which works the same way as your real account, except all trades are done with play money. Use that as a testing/debugging option, rather than unleashing an untested and possibly buggy script on your actual account!

IMPORTANT: Do NOT use this function in conjunction with an indicator that is set to update every tick, unless you want to enter hundreds of orders in a single bar!

Example:

ref1 = IB_PlaceOrder("buy",1,close,"market","day",""); # this will buy one contract at market


IB_CancelAll

Syntax:

ib_cancelall( )

Description:

Use this function to cancel all orders placed for a particular symbol. This function will also cancel any orders placed manually for this symbol.

Example:

ref1 = IB_PlaceOrder("buy",1,close+1.5,"stop","day",""); #places an order to buy on a stop

ref1 = IB_PlaceOrder("buy",1,close+3.5,"stop","day",""); #places another order to buy on a stop

IB_CancelAll(); #cancels both orders, and any others that were pending


IB_CancelOrder

Syntax:

ib_cancelorder(orderid)

Description:

Use this function to cancel a specific order. The OrderId value is the identifier for the particular order to cancel, and is the same as the value returned from the IB_PlaceOrder function. Returns a value of true if the cancellation went through successfully, and false if the order was unable to be canceled (for example, if it was filled, or if the order number was incorrect).

Example:

ref1 = IB_PlaceOrder("buy",1,close+1.5,"stop","day",""); # places an order to buy on a stop

IB_CancelOrder(ref1); # cancels the order


IB_OrderStatus

Syntax:

ib_orderstatus(orderid)

Description:

Use this function to check the status of a particular order. OrderId is the order number for the particular order, as returned by IB_PlaceOrder. This function will return a string value that describes the status of the order. There are five possible return values:

active = the order is active and pending.

badserver = you need to be running on Interactive Brokers with order placement enabled for this function to work.

canceled = the order was cancelled.

filled: x of y = the order was filled, specifically X contracts out of Y contracts were bought or sold. If X and Y are different, you had a partial fill, and some portion of the order is still pending.

unknown = QScript was unable to find an order with an order number as entered.

Example:

ref1 = IB_PlaceOrder("buy",1,close+1.5,"stop","day",""); #places an order to buy on a stop

status = ib_orderstatus(ref1); # will return "active" if the order hasn't been filled yet


IB_MarketPosition

Syntax:

ib_marketposition( )

Description:

Use this function to determine what your current open position is for the chart symbol. Positive numbers indicate a long position, negative numbers indicate a short position, and a value of zero indicates a flat position. The number itself will represent how many contracts long or short the account is.

Example:

ref1 = IB_PlaceOrder("sell",5,close,"market","day",""); #places an order to sell 5 contracts at market

mp = ib_marketposition( ); # mp will hold a value of -5, meaning short 5 contracts


IB_AverageFill

Syntax:

ib_averagefill

Description:

Use this keyword to determine what your average entry price is for the current open position, including commission costs. Only valid when an open position currently exists (see IB_MarketPosition ).

Example:

ref1 = IB_PlaceOrder("sell",5,close,"market","day",""); #places an order to sell 5 contracts at market

print "avg fill = ", ib_averagefill; # prints the average fill price to the print log


IB_GoMarketAtTime

Syntax:

ib_gomarketattime(orderid, year, month, day, hour, minute, second)

Description:

Use this function to go to market with a particular order at a specified time of day. The order must have already been placed using IB_PlaceOrder , and it's OrderID value returned. When the time and day matching the parameters approaches, and the order has not yet been filled, Wave59 will execute it at the market price. Note that Wave59's internal timer for this function runs on a 5 second interval, so a 5 second slop factor must be allowed. Therefore, make sure to enter a time at least 5 seconds earlier than the latest time you require to be filled by.

Important Note: Manually adjusting orders on the chart will frequently change their OrderIds. Therefore, for this function to work, the order MUST NOT be adjusted by hand. Otherwise, the timer will not be able to locate the appropriate order to take to market.

Example:

# assume a daily chart with endtime = 1414, one minute before the day session close on a computer on Mountain Time

ref1 = IB_PlaceOrder("sell",5,close,"limit","day",""); # places an order to sell 5 contracts on a limit at the closing price

IB_GoMarketAtTime(ref1,year,month,day,14,14,30); # if the order is not filled by 14:14:30, just take it to market


IB_GetAccountValue

Syntax:

ib_getaccountvalue(value)

Description:

Use this function to query TWS for various account values. The Value parameter defines which account value Wave59 should fetch, and can be any of the following strings, which must be entered exactly as follows:

AccountDescription

CashBalance

Currency

DayTradeEquity

DayTradesRemaining

EquityWithLoanValue

FutureOptionValue

FuturesPNL

GrossPositionValue

InitMarginReq

Leverage

LongOptionValue

MaintMarginReq

NetLiquidation

OptionMarketValue

PreviousDayEquityWithLoanValue

RealizedPnL

ShortOptionValue

StockMarketValue

UnalteredInitMarginReq

UnalteredMaintMarginReq

UnrealizedPnL

The function returns a string value containing the value as reported by TWS. To convert the string value to a number (if applicable), use the functions to_int , or to_double .

Example:

cashbalance = IB_GetAccountValue("CashBalance"); # returns a value like "1000000.00"

cashbalance = to_double(cashbalance); # convert to a numeric value which can be used in plot statements, etc


Calc_Ashtakavarga_Bindus

Syntax:

calc_ashtakavarga_bindus(natal_jd, latitude, longitude, planet, bindu_array)

Description:

This function computes the bindu counts in each sign based on the Ashtakavarga method. Ashtakavarga is a technique from Vedic Astrology used to determine how weak or powerful a particular zodiac sign is for a particular planet based on a person's (or market's) birth date. Each planet will receive a numeric score from 0 to 8 for each zodiac sign. Signs with scores of 5 or higher are considered to be strong, signs with scores of 3 or lower are considered to be weak, and a score of 4 is right in the middle, neither weak nor strong.

The following parameters are used:

natal_jd: This is the date for which to calculate the bindus. Traditionally this corresponds to a birthday or first trade date. Use the julianday function to compute this value.

latitude: The latitude of the geographical place on Earth to compute for.

longitude: The longitude of the geographical place on Earth to compute for.

planet: The id value of the planet to compute for. See the astro function for details. Note that this function only works with Mercury through Saturn, plus the Moon. The outer planets of Uranus, Neptune, Pluto, and asteroids are not used in Vedic astrology.

bindu_array: This is a QScript array in which the bindu counts will be returned. Any previous values in the array will be erased when passed to this function. bindu_array[0] will contain the bindu count for Aries, bindu_array[1] will contain Taurus, etc, up to Pisces at bindu_array[11].

Note that this function uses the sidereal zodiac. Make sure any other planetary calculations (current planets transiting through zodiac signs, etc) are also computed using the sidereal zodiac, otherwise you will be mixing coordinate systems and will have incorrect results.

For more information on Ashtakavarga, please consult the following references:

Digital Astrology, by Richard Houck

Dots of Destiny, by Vinay Aditya

Example:

define ARRAY bindus[]; # define our array

jd = julianday(1982,4,21,730); # the birthday of the SP on a computer running in Mountain Time

lat = 40.707518; # latitude of NY

lon = 74.011335; # longitude of NY

calc_ashtakavarga_bindus(jd,lat,lon,astro_moon,bindus); # calculate bidus for the moon

print bindu[0]; # print the bindu count for Aries

print bindu[3]; # print the bindu count for Cancer


Use_Holiday_List

Syntax:

use_holiday_list

Description:

Returns true if holidays are being removed from the chart according to the dates found in the holiday list, returns false if not. To edit the holiday list, go Format - Chart - Holidays.

Example:

if (use_holiday_list == true)

{

print "holiday list is active.";

}


System Testing, Optimization, and Automation

System Testing

You can create custom trading systems within QScript using various build in functions such as:

BarsSinceEntry

Buy

CancelAll

CancelOrder

EntryPrice

EquityCurve

ExitLong

ExitShort

FillAction

FillBar

FillPrice

FillQty

MarketPosition

NextOpen

NumTrades

OpenEquity

Sell

SetOCOTag

TradeResult

WasOrderFilled

In order to backtest a system you must enter orders to buy and sell as your script runs through the chart. Once the entire script has been run, these orders will be compiled into a system report which you can study to learn the characteristics of your trading system. The system report can be accessed by clicking Systems - System Report from the chart where your system has been applied.

A trading system consists of various rules, which tell Wave59 when to go long or short, and when to exit the position. Once you have determined what your rules are, you need to enter them into your script using the Buy , Sell , Exitshort , and Exitlong functions. For example, lets say you wanted to create a day trading system that bought when a faster moving average crossed over a slower one, and sold when the faster average crossed under the slower one. That script would look something like this:

input:fastlen(8),slowlen(20);

fastavg=average(close,fastlen);

slowavg=average(close,slowlen);

if ((fastavg crosses over slowavg) and (marketposition<=0))

{

buy(1,close,"market","onebar");

}

if ((fastavg crosses below slowavg) and (marketposition>=0))

{

sell(1,close,"market","onebar");

}

Note that a buy signal will exit and reverse on any short positions entered, and that a sell signal will reverse on any long positions entered. Also note that we can enter multiple contracts in the same direction, so we need to use the marketposition keyword to test and make sure not to increase our position size by purchasing extra contracts in the same direction we are already going. More information can be found on the pages detailing these individual functions.

Let's apply this to a 5min chart of the ES over the last 5-6 weeks:

You can see that various blue and red arrows have appeared on our chart. These are the points at which our system bought and sold according to our rules. Let's look at the system report and see how we did. This is done by clicking System - System Report, which brings up the following settings box:

To arrive at correct profit and loss numbers, Wave59 needs to know two pieces of information, how much each 1.0 of price movement is worth in dollars, and what our initial account size is. We are trading the ES, which is worth $50 per point, so we enter 50 in the first box, and enter $100,000 in the second. The account size is used to compute percentage drawdowns. Note that on the right side of the setting box we have our system name ("test7"). If we had more than one system running on this chart, we would have the option to select a single system or any combination when computing our system report. Combined system reports are used to give an idea how an account would do with multiple systems acting upon it at once.

Our system report looks as follows:

Our system made $3000 over this time period, but was only 40% accurate. Many other interesting pieces of information are shown on the report. We can investigate each trade by clicking on the "Trade by Trade" tab at the top:

Our equity curve can be viewed by clicking the "Equity Curve" tab:

Note that this chart is interactive. Click and drag on it to view the value at your cursor. We can also view our results tabulated by year ("Annual Results" tab) or by month ("Monthly Results" tab).

Optimization

Now that we've had a look at our system, we might want to run it through the optimizer to see how it performs using different parameters than the ones we've chosen. If we click Systems - Optimize - Brute Force, the following setup window pops up:

From here, we can select which system to optimize (in our case, it is "test7"), and as in the system report, we need to enter the contract dollar value per point and our initial account value. Our parameter list is shown at the top. These are the values we'd like to try variations on. First, we click Add an Optimization Variable to reach the following screen:

Note at the top we have a message that says "Your Optimization Variable is: #1#". What this means is that we can type in a #1# in our parameter list to replace one of our fixed parameters, and then can set that value to be a series of numbers of our choosing. So instead of using a value of "8" for our fast average length, as shown, let's say we want to see what happens with values starting at 5 and ending at 15. We can do that by replacing our 8 with our optimization variable and setting the search field appropriately. That would look like this:

So now we've got our 8 replaced, and our optimization range is from 5 to 15 in steps of 1. This means the optimizer will initially set #1# to 5, then it will increase to 6, 7, 8, etc, all the way up to 15. Click OK to return to the setup form:

You can see that our Optimization Variable is now in our parameter list, and that the range is shown in the list at the bottom. Now lets do the same thing for our longer moving average length, by clicking Add Optimization Variable again.

After we've entered that value and returned, the setup page will look as shown above. I chose to optimize the second parameter (#2#) from 15 to 50 in steps of 5, so we'll get values 15, 20, 25, ..., etc, up to 50. When done, click Begin Optimization, and Wave59 will run through all the various combinations.

This is a list of all our combinations. This list is initially sorted by optimization parameter, but by clicking on any of the headings at the top, we can sort by that metric. In this example, I've sorted by Profit by clicking on the "Profit/Loss" column heading. You can see that the optimizer discovered a parameter set that made $5112 over our test period, significantly more profitable than the random setting we chose when programming this system.

Keep in mind that an optimizer just tries many different combinations of indicators. It is not designed to create profitable systems, but to test the stability of particular systems. If run an optimization and discover one really profitable combination, but 99 unprofitable ones, odds are that the profitable combination was a fluke, and that system will likely lose money when traded in real time. Conversely, if most of your combinations are profitable, odds are you have a robust methodology that should hold up in real time.

Autotrading

Once we have created a system and are satisfied with it, we have the ability to automate it so that orders are placed for us by the software. This can be done using an account with Interactive Brokers, and the various IB order placement functions provided with QScript. This will typically require a bit of code rewriting, but should be relatively painless.

The IB autotrading functions available within QScript are:

IB_AverageFill

IB_CancelAll

IB_CancelOrder

IB_GetAccountValue

IB_GoMarketAtTime

IB_MarketPosition

IB_OrderStatus

IB_PlaceOrder

The PFG autotrading functions are:

PFG_AccountBalance

PFG_AverageFill

PFG_CancelAll

PFG_CancelOrder

PFG_GoMarketAtTime

PFG_MarketPosition

PFG_OrderExists

PFG_PlaceOrder

The single most important rule in converting a hypothetical system to one that runs live is to always do testing using a paper trading account! Most brokers offer free paper accounts to all their clients, which include a separate username and password. Make sure the system performs correctly on your paper account before you risk it on your live account. The last thing you want to do is forget to test marketposition before entering a trade, then accidentally run up a position of 100 contracts when you only meant to trade 1. That sort of thing is annoying in a paper account situation, but could be devastating after letting an untested script loose on your live account!


Sleep

Syntax:

sleep(seconds)

Description:

This is used to put Wave59 to sleep for a fixed number of seconds. This is usually not useful unless doing very exotic system testing by hand using updated variables that get saved out to a file, then reloaded onto a script using a call to recalculate_all . Recalculate_All can't be called more than one time in 3 seconds, so sleep would be used to send Wave59 into hibernation for a period of time so that the next call was valid. This is a specialized function and shouldn't be used in the average indicator script - usually we want to speed things up, rather than slow them down!

Example:

sleep(4); # puts wave59 to sleep for four seconds

recalculate_all( ); # reload the chart and recalculate everything (as this is written, it is an infinite loop)


Delete_Script

Syntax:

delete_script( )

Description:

When this function is called, the script will be deleted from the chart in the same way as if the user clicked Format - Indicators - Current Indicator - Delete. Note that the deletion happens after the script has run all the way through the entire chart, even if delete_script was called on the first bar. When used in conjunction with Spawn , this function enables creating indicator templates programmatically through QScript.

Example:

print "barnumber = ",barnum; # writes all the bars to the script log

delete_script( ); # tells Wave59 to delete the script after it completes


Spawn

Syntax:

spawn(indicator_name, parameter_list)

Description:

This function applies an indicator to the chart in the same way as if a user clicked the Technical menu and selected an indicator to apply. The indicator name needs to be the same as shown in the Technical menu, and the parameter list needs to be a comma-delimited list of parameters that corresponds to what is shown after the indicator is added using the Technical menu. Keep in mind that a new indicator will be spawned each time this function is called, so it's best to include it in an "if (barnum==barsback)" loop, unless you want to add an indicator for each bar on your chart.

Example:

if (barnum==barsback) # only run this once

{

spawn("average","close,10,red,1,0"); # add a 10-bar moving average

spawn("average","close,15,blue,1,0"); # add a 20-bar moving average

delete_script( ); # delete this script now that the averages have been added

}


Reload_Script

Syntax:

reload_script(parameter_list)

Description:

This function changes the inputs in the script, and reloads it on the chart in the same way as if the user clicked format - indicators - change settings. It only changes the input list for the top level indicator, not for any functions that the indicator called. This means that if reload_script is called in a function, it needs to pass the new parameters for the calling indicator, not the parameters for the function that executed it. The parameter_list input is a comma-delimited string of new parameters to use for the indicator.

Unless a stopping condition is provided, this function will result in an infinite loop, as each pass will result in another reload call. Also note that this function will reload the indicator one time each call, so it's best to include it in a (barnum==updating_bar-1) block to prevent multiple calls.

Example:

input: one(3), two(5), three(7); # assume these inputs when the script is first applied

if (barnum==barsback) # only run this block once

{

print one,two,three; # prints 357 to the script log

if (one == 3) # only change the inputs if one is set to a value of 3

{

reload_script("4,6,8"); # this causes the script to reload, and will print 468 to the script log

}

}


SocketSend

Syntax:

SocketSend(IP, Port, Text)

Description:

This function initiates a socket connection on the given IP and Port, and sends out whatever text is passed through the Text parameter. A waiting server client must be available on the other end to catch the incoming text.

Example:

SocketSend("127.0.0.1",5901,"This text comes from QScript");


ActionZones

Syntax:

ref = ActionZones(&s1, &r1, &s2, &r2)

Description:

This function returns the four ActionZone support and resistance levels. The support levels are returned in s1 and s2, and the resistance levels are returned in r1 and r2. Note that this is done via reference variables , so the ampersand symbol (&) is needed for the inputs in order for the function to work properly. The function itself returns either true or false, which indicates whether or not the levels are valid. Note that even though the levels remain the same for the entire day, the function still needs to be called every bar in order to maintain proper internal arrays.

Example:

# call the function

ref = ActionZones(&s1, &r1, &s2, &r2);

# plot s1 on the chart if the value is valid

if (ref == true) {

plot1 = s1;

}


WebUpload

Syntax:

WebUpload(url, attachment, controlname)

Description:

This function uploads a file to RFC1867-compliant web servers. A web page will need to be created that processes the uploaded file on the server end. For a free solution, please check out "FreeASPUpload" on the web. URL is the target url to upload to, attachment is the target file to upload, and controlname is the name of the web control that the processing page expects.

Example:

WebUpload("http://www.mywebsite.com/mypage.asp", "myfile.txt", "attachment1");


Hive_Init

Syntax:

Hive_Init(numinputs)

Description:

This function is used as part of the QScript implementation of Hive Technology. In most cases, using Wave59's Hive Designer is the preferred method to implement hives, but it can also be done directly in QScript. This function needs to be called once before any other hive functions, with the correct number of inputs (numinputs) into the hive. This function returns a reference number which must be passed in to all future hive manipulation functions.

Example:

if (barnum==barsback) {

ref = hive_init(10);

}


Hive_UpdateData

Syntax:

Hive_UpdateData(ref, barnumber, price)

Description:

This function is used as part of the QScript implementation of Hive Technology. In most cases, using Wave59's Hive Designer is the preferred method to implement hives, but it can also be done directly in QScript. This function is used to keep the hive up-to-date on the data set the inputs are trading. It must be called once per bar, and needs to be done before any calls to hive_updateinput or hive_execute . Ref is the hive reference number as returned by the Hive_Init function, barnumber is the bar number the data corresponds with, and price is the price value of the data set the hive is trading on.

Example:

hive_updatedata(ref, barnum, close);


Hive_UpdateInput

Syntax:

Hive_UpdateInput(ref, barnumber, input_number, input_value)

Description:

This function is used as part of the QScript implementation of Hive Technology. In most cases, using Wave59's Hive Designer is the preferred method to implement hives, but it can also be done directly in QScript. This function is used to keep the hive up-to-date on the inputs that it is using to make trading decisions. Each bar, all inputs must be passed into this function. Ref is the hive reference number as returned by Hive_Init , barnumber is the current bar number , input_number is the index (0-based) of the particular input that is being passed, and input_value is the value of the particular input.

Example:

avg = average(close,10);

hive_updateinput(ref, barnum, 0, avg);


Hive_Execute

Syntax:

Hive_Execute(ref, barnumber)

Description:

This function is used as part of the QScript implementation of Hive Technology. In most cases, using Wave59's Hive Designer is the preferred method to implement hives, but it can also be done directly in QScript. This function is used to execute a hive and get it's return value, which will be a number between -1 and +1 that describes how bearish or bullish the hive is on the current market. Before being called, Hive_UpdateData and Hive_UpdateInput need to have been called to keep the hive up-to-date on the status of the market and all inputs. Ref is the hive reference number as returned by the Hive_Init function, and barnumber is the bar number to retrieve the signal for.

Example:

signal = hive_execute(ref, barnum);


GetData

Syntax:

GetData(symbol_index, data_type, offset)

Description:

This function can be used to request data from a chart with multiple symbols loaded. Multiple symbols can be loaded onto a chart by entering a comma-delimited list in the symbol field when setting up the chart. For example a symbol of "S.IBM, S.MSFT, S.CAT" would load a chart of IBM data, but would also load MSFT and CAT in the background. Symbol_Index tells GetData which symbol to retrieve information for. Symbol_Index is 0-based, so a value of 0 is the 1st symbol loaded, a value of 1 is the 2nd symbol loaded, etc. Data_Type tells the function what data point to load from the symbol. Use one of the following keywords:

dtOpen

dtHigh

dtLow

dtClose

dtVolume

dtTickVolume

dtBidVolume

dtAskVolume

dtOpenInterest

Finally, offset works in the same way as standard QScript offsets , specifying how many bars back to load data for. A value of 0 would be for the current bar, a value of 1 would be for the bar immediately before the current bar, a value of 2 would be two bars back, etc.

Example:

my_close = GetData(1, dtClose, 0); # returns the close of whatever data has been loaded second in the symbol list


Tick_Volume

Syntax:

tick_volume[offset]

Description:

Returns the tick volume of the given bar.

Example:

a = tick_volume; # a holds the tick volume of the current bar

a = tick_volume[1]; # a holds the tick volume of the bar right before the current bar


Bid_Volume

Syntax:

bid_volume[offset]

Description:

Returns the bid volume of the given bar.

Example:

a = bid_volume; # a holds the bid volume of the current bar

a = bid_volume[1]; # a holds the bid volume of the bar right before the current bar


Ask_Volume

Syntax:

ask_volume[offset]

Description:

Returns the ask volume of the given bar.

Example:

a = ask_volume; # a holds the ask volume of the current bar

a = ask_volume[1]; # a holds the ask volume of the bar right before the current bar


Open_Interest

Syntax:

open_interest[offset]

Description:

Returns the open interest of the given bar. Only valid for Futures markets.

Example:

a = open_interest; # a holds the open interest of the current bar

a = open_interest[1]; # a holds the open interest of the bar right before the current bar


PFG_CancelAll

Syntax:

pfg_cancelall( )

Description:

Use this function to cancel all orders placed for a particular symbol. This function will also cancel any orders placed manually for this symbol.

Example:

ref1 = PFG_PlaceOrder("buy",1,close+1.5,"stop","day"); #places an order to buy on a stop

ref1 = PFG_PlaceOrder("buy",1,close+3.5,"stop","day"); #places another order to buy on a stop

PFG_CancelAll(); #cancels both orders, and any others that were pending


PFG_PlaceOrder

Syntax:

PFG_PlaceOrder(buysell, qty, price, type, tif)

Description:

Use this function to place an order through PFG. This order requires that Wave59 be using PFG with order entry as the data feed. The order will be placed in exactly the same way as if you were trading off the chart using the manual order placement tools. Once placed, the order will return a unique order number which can be used to cancel or check the status of the order later. Note that Wave59 will not allow orders to be placed on any bar except the most recent. Also note that this function will not place any orders if the script is being debugged.

The following parameters are required:

buysell: can be "buy", "sell" , or "short".

qty: the quantity to buy or sell.

price: the price to buy or sell at (ignored for market orders).

type: the order type. Can be "stop", "limit", or "market".

tif: time in force, either "day" or "gtc".

It is highly recommended that all mechanical systems using this function be tested using Interactive Brokers' paper trading account option, which is a free service available to all account holders. PFG will issue a special username/password which works the same way as your real account, except all trades are done with play money. Use that as a testing/debugging option, rather than unleashing an untested and possibly buggy script on your actual account!

IMPORTANT: Do NOT use this function in conjunction with an indicator that is set to update every tick, unless you want to enter hundreds of orders in a single bar!

Example:

ref1 = PFG_PlaceOrder("buy",1,close,"market","day"); # this will buy one contract at market


PFG_CancelOrder

Syntax:

pfg_cancelorder(orderid)

Description:

Use this function to cancel a specific order. The OrderId value is the identifier for the particular order to cancel, and is the same as the value returned from the PFG_PlaceOrder function.

Example:

ref1 = PFG_PlaceOrder("buy",1,close+1.5,"stop","day"); # places an order to buy on a stop

PFG_CancelOrder(ref1); # cancels the order


PFG_MarketPosition

Syntax:

pfg_marketposition( )

Description:

Use this function to determine what your current open position is for the chart symbol. Positive numbers indicate a long position, negative numbers indicate a short position, and a value of zero indicates a flat position. The number itself will represent how many contracts long or short the account is.

Example:

ref1 = PFG_PlaceOrder("sell",5,close,"market","day"); #places an order to sell 5 contracts at market

mp = pfg_marketposition( ); # mp will hold a value of -5, meaning short 5 contracts


PFG_AverageFill

Syntax:

pfg_averagefill( )

Description:

Use this function to determine what your average entry price is for the current open position. Only valid when an open position currently exists (see PFG_MarketPosition ).

Example:

ref1 = PFG_PlaceOrder("sell",5,close,"market","day"); #places an order to sell 5 contracts at market

print "avg fill = ", pfg_averagefill; # prints the average fill price to the print log


PFG_OrderExists

Syntax:

pfg_orderexists(orderid)

Description:

Use this function to determine whether or not a particular order exists. This is useful to verify order numbers before issuing cancellation/go-to-market requests. The order number is the return value from the PFG_PlaceOrder function.

Example:

ref1 = PFG_PlaceOrder("sell",5,close,"stop","day""); #places an order to sell 5 contracts

if (pfg_orderexists(ref1) == true) {

print "Order has been placed";

}


PFG_GoMarketAtTime

Syntax:

pfg_gomarketattime(orderid, year, month, day, hour, minute, second)

Description:

Use this function to go to market with a particular order at a specified time of day. The order must have already been placed using PFG_PlaceOrder , and it's OrderID value returned. When the time and day matching the parameters approaches, and the order has not yet been filled, Wave59 will execute it at the market price. Note that Wave59's internal timer for this function runs on a 5 second interval, so a 5 second slop factor must be allowed. Therefore, make sure to enter a time at least 5 seconds earlier than the latest time you require to be filled by.

Important Note: Manually adjusting orders on the chart will frequently change their OrderIds. Therefore, for this function to work, the order MUST NOT be adjusted by hand. Otherwise, the timer will not be able to locate the appropriate order to take to market.

Example:

# assume a daily chart with endtime = 1414, one minute before the day session close on a computer on Mountain Time

ref1 = PFG_PlaceOrder("sell",5,close,"limit","day"); # places an order to sell 5 contracts on a limit at the closing price

PFG_GoMarketAtTime(ref1,year,month,day,14,14,30); # if the order is not filled by 14:14:30, just take it to market


Astrotrader_Energy

Syntax:

astrotrader_energy(jd, influences, aspects, sensitive_points, latitude, longitude, use_etheric, etheric_delay, use_ecliptic, orb)

Description:

Returns the AstroTrader energy value for the given moment, as described in Techniques of an Astrotrader. Note that this function will only work when called from a Wave59 PRIVATE edition. Parameters are:

JD: the Julian date for the moment. Use the julianday function to calculate this.

Influences: a string of eleven 1's and 0's to determine which planetary bodies to consider in the energy function. The order is Moon, Mercury, Venus, Sun, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto, and Node. For example, an influences value of "11011111111" would calculate an energy value using all the planets except Venus.

Aspects: a comma-delimited list of aspects to use when calculating energy. For example "0,90,180,360," would calculate squares. Note that any aspect over 180 will get resolved down to an aspect below 180 (so 90 and 270 are the same), and also note that 360 and 0 both need to be added to the list.

Sensitive_Points: Similar to influences, a 4-character string or 1's or 0's to tell QScript which of the four geographical points to use when calculating the energy composite. The order is Ascendant, Midheaven, Descendant, and Immum Coeli. For example, a sensitive_points value of "1000" would calculate an energy value only using the Ascendant.

Latitude: The latitude of the geographical location to compute the energy for. Positive for North hemisphere.

Longitude: The longitude of the geographical location to compute energy for. Positive for west of Greenwich, negative for east of Greenwich.

Use_Etheric: if true, QScript will use etheric planetary positions. If false, QScript will use normal planetary positions.

Etheric_Delay: the delay factor to use when calculating etheric positions, in Astronomical Units. Enter a -1 to use the default 1 AU setting. This setting only applies when use_etheric is set to true.

Use_Ecliptic: if true, QScript will use ecliptic planetary positions. If false, QScript will use equatorial positions.

Orb: How wide of an orb (in degrees) to use when computing the energy function. Default value is 6.

Example:

jd = julianday(year, month, day, time); # compute JD for this moment

influences = "11111111111"; # all the planets

aspects = "0,60,90,120,180,360,"; # aspects to use, note 0 and 360 are both in the list, and that the final character is a comma

sensitive = "1111"; # use all the points

lat = 40.705; # ny lat

lon = 74.008; # ny long

use_etheric = false; # don't use etherics

etheric_delay = 1; # etheric delay factor (not used)

use_ecliptic = false; # use equatorial, not ecliptic

orb = 6; # orb of 6 degrees

at = astrotrader_energy(jd, influences, aspects, sensitive, lat, lon, use_etheric, etheric_delay, use_ecliptic, orb); # compute the result


PFG_AccountBalance

Syntax:

pfg_accountbalance(keyword)

Description:

Use this function to get information about PFG account balances. Different items will be returned depending on what keyword is set to. The following possibilities are available:

Cash

LiqValue

MarginReq

MarginEq

OpnBal

CloseBal

NetChg

EquityCash

SDFull

OvernightMktValue

CashBalance

AvailableEquity

OvernightEquity

OpeningExcessEquity

ScalpedProfit

OpeningMargin

IntradayMargin

Passing any of these items in as the keyword will result in that value being returned by the function. Note that these keywords are not case sensitive. Alternatively, you may also use the "ALL" keyword, which will return a list of all balances in a comma-delimited string value.

Example:

cash = PFG_AccountBalance("cash"); # returns the current cash balance for the account