Upload
others
View
3
Download
0
Embed Size (px)
Citation preview
http://www.tradestation.com/why-tradestation/tour/extend-the-possibilities/easylanguage
December 17, 2012 2 Code Monkeys Drinking Delta Tea
December 17, 2012 3 Code Monkeys Drinking Delta Tea
Trade Tool
Code Monkey Toy
Relative Volume
Vectors
Composite of Internals
Price Series Providers
Drawing Levels and Areas of Interest
Text File I/O, TokenList
“1-Click” Levels Update
Forms and Controls, Global Dictionary
Object-oriented programming (OOP) is a programming paradigm using "objects" – usually instances of a class – consisting of data fields and methods together with their interactions – to design applications and computer programs. ◦ http://en.wikipedia.org/wiki/Object-
oriented_programming
It is a way to make the very complex easier to use.
December 17, 2012 4 Code Monkeys Drinking Delta Tea
Relative Volume is the percentage of current volume compared to some historical volume.
Examples: ◦ If the prior 10 day simple moving average of daily
volume is X, and today’s total volume is Y
Rel volu = 100 * Y / X
“Percentages” are easier to deal with / to read
◦ How about if, for 1minute bars, the prior 50 day at 0931ET simple moving average was X and this real time bar volume is Y
That’s cool …
December 17, 2012 5 Code Monkeys Drinking Delta Tea
A Vector is a data structure that allows indexing to a collection of data or objects.
Suppose you wanted something that corresponded to each minute of the day? // initialize volu history vector of vectors
mondoVect = New Vector; // our vector of vectors
// This actually creates one extra entry, as 0 &1440 are “same time bar“
For jIdx = 0 to MinutesPerDay begin
mondoVect.push_back(New Vector);
// populate our vector of vectors, 1 per minute & empty!! Initz on demand
end;
Why is that cool? ◦ The code can be indexed by minutes after midnight, so if I want the 9am
minute vector, it is easy to get
◦ Each minute vector can have any data or object in it
What might that be?
December 17, 2012 6 Code Monkeys Drinking Delta Tea
// get historic bar time data vector Method Vector getMinVector(int inTime) Variables: int jIdx, Vector retVect, int fromTime; Begin fromTime = inTime;
// need this for TS EL to deal with input / variable properly jIdx =TimeToMinutes(fromTime);
// mondoVect is indexed by the closing time of the bar, in minutes from midnight retVect = mondoVect.Items[jIdx] astype Vector; // get the vector that corresponds to this bar time slot If retVect.Count = 0 then begin
// does the minVect need to be initialized? Initz on demand For jIdx = 0 to daysBackAvgLength begin
// for the simple moving average length retVect.push_Back(0 astype double);
// put zeros in the vector, as data type double end; end; Return retVect; end;
December 17, 2012 7 Code Monkeys Drinking Delta Tea
EndOfBar = BarStatus(1) = 2 ;
// When this goes true HERE we are at end of bar
If EndOfBar then begin
// closing tick of the bar. On next tick, we'll have a fresh bar
minVect = getMinVector(Time);
// get the current time vector
minVect.push_back(Upticks + Downticks);
// push this bar's volu into the minute vector
minVect.erase(0);
// remove the oldest volu data from the minute vector
end;
December 17, 2012 8 Code Monkeys Drinking Delta Tea
// given a vector of volu values, get average and cumu Sum History Method void getPlotValues (Vector inVect) Variables: int jIdx, double runningSum, double vectValue; Begin barAvg = 0; runningSum = 0; For jIdx = 1 to daysBackAvgLength begin // for the simple average length of interest vectValue = inVect.Items[jIdx] astype double; // get each value from the vector runningSum = runningSum + vectValue;
// sum up to prep for simple average calc end; barAvg = runningSum / daysBackAvgLength; // simple average cumuSumHistory = cumuSumHistory + barAvg;
// cumulative sum of average bar volu end;
December 17, 2012 9 Code Monkeys Drinking Delta Tea
Suppose you wanted to plot @ES and $Tick on the same chart, for example. ◦ Put both symbols on a time based chart
Suppose you wanted to put $Tick on a 1500 tick @ES chart? ◦ Nope. No multi-symbol tick (or other non-time)
charts allowed.
Suppose you wanted to put a composite of internals on any arbitrary chart?
PriceSeriesProvider’s (PSP’s) enable that …
December 17, 2012 11 Code Monkeys Drinking Delta Tea
Method PriceSeriesProvider buildPSP(string aSymbol)
Variables:
PriceSeriesProvider retVal;
Begin
retVal = new PriceSeriesProvider;
retVal.Symbol = aSymbol;
retVal.Interval.ChartType = DataChartType.bars;
retVal.Interval.IntervalType = DataIntervalType.ticks;
retVal.Interval.IntervalSpan = 20;
retVal.Interval.Name = "(unknown name)";
retVal.Range.Type = DataRangeType.weeks;
retVal.Range.Weeks = 5;
retVal.Range.Name = "(unknown name)";
retVal.IncludeVolumeInfo = false;
retVal.IncludeTicksInfo = false;
retVal.Load = true;
retVal.Realtime = true;
retVal.Name = aSymbol;
Return retVal;
end; December 17, 2012 12 Code Monkeys Drinking Delta Tea
Method void buildInternalsPSPs() Begin tickPSP = buildPSP("$TICK"); addiffsPSP = buildPSP("$ADSPD"); volspdPSP = buildPSP("$VOLSPD"); End; Method void getInternalsData() Begin myTick = tickPSP.Close[0]; myAdd = addiffsPSP.Close[0]; myVoldsp = volspdPSP.Close[0]; End;
December 17, 2012 13 Code Monkeys Drinking Delta Tea
There are issues building the Open High Low Close bars.
December 17, 2012 14 Code Monkeys Drinking Delta Tea
December 17, 2012 15 Code Monkeys Drinking Delta Tea
getInternalsData(); getValueScores(); getSlopeScores(); sigRaw = getAvg();
Suppose you had a data service provider that sold “levels of interest” for trading @ES? ◦ 1419.50,1421.50,R,Normal
◦ 1415.50,1416.75,R,Normal
◦ 1412.00,1412.00,L,Normal
Suppose you had 2 data service providers ? ◦ 1388.25,aoi
◦ 1401,sup
◦ 1395.50,sup
◦ 1392.75,sup
December 17, 2012 16 Code Monkeys Drinking Delta Tea
Suppose you wanted to plot the stuff on a chart?
December 17, 2012 17 Code Monkeys Drinking Delta Tea
Suppose you wanted it on a lot of charts?
begin
myRoot = “… blanked to keep vendor private…”
myToday = CurrentDate;
numZones = 0;
For iIdx = 0 to daysBack Begin
Try // this is JUST to allow cycling thru date tagged files
myToday = CalcDate(CurrentDate, -iIdx) astype int;
workFile = myRoot + Numtostr(myToday,0) + ".txt";
myReader = StreamReader.Create (workFile);
repeat
myLine = myReader.ReadLine(); // Read a line of data
parseInputLine(myLine, aLo, aHi, anSR, aStrength); // parse it var's
numZones = numZones + 1; // one more line eaten
pVal[numZones,idxLo] = aLo; // shuffle stuff into the arrays
pVal[numZones,idxHi] = aHi;
pVal[numZones, idxDate] = myToday;
pValStringData[numZones, idxSR] = anSR;
pValStringData[numZones, idxStrength] = aStrength;
until (myReader.EndOfStream = True); // Continue until no more data
myReader.Close();
Catch (elsystem.io.filenotfoundexception ex)
end;
end;
end; December 17, 2012 18 Code Monkeys Drinking Delta Tea
Method void parseInputLine(string inLine, out double theLow, out double theHigh, out string theSR, out string theStrength)
Variables: TokenList theDataLine; begin theDataLine = TokenList.create( inLine ) ; theLow = StrToNum(theDataLine.Item[0]); theHigh = StrToNum(theDataLine.Item[1]); theSR = theDataLine.Item[2]; theStrength = theDataLine.Item[3]; end;
December 17, 2012 19 Code Monkeys Drinking Delta Tea
This is a line of data 1415.50,1416.75,R,Normal
After the file reading is complete, all of the vendor supplied data is in internal data structures.
Then comes the very long (lots of lines of code) task of building the trend lines.
But it’s much better than doing it by hand.
And … ◦ But that’s the next part of the story …
December 17, 2012 20 Code Monkeys Drinking Delta Tea
At start up, TradeStation loads and redraws all the Zones / Levels / Areas of Interest
Around 0900ET, the data vendors do their homework and let you know there’s new data.
How do you cope with that? ◦ Go to every chart, and right click disable indicator, then
right click enable indicator.
That gets old fast with a lot of charts
◦ Restart TradeStation, a very brute force disable / enable
You’re not stressed 15 minutes before the open, are you?
◦ Push a button and restart all the indicators
Even I can do that …
December 17, 2012 22 Code Monkeys Drinking Delta Tea
This is a chart
These are indicators, without plots, just so I can see them easily
This is a form
These are controls
December 17, 2012 23 Code Monkeys Drinking Delta Tea
Create the form Method void makeForm()
Begin
eventFireControl = Form.Create("Punch a Button", 155, 520);
// undisplayable title, form width, height
eventFireControl.Dock = DockStyle.right;
// anchored to right side of chart
December 17, 2012 24 Code Monkeys Drinking Delta Tea
That’s it. Two lines, one form on a chart.
Button Class ◦ Displays a push button control within a container in a form. A Click event is fired
when the button is pressed. ◦ The name of the button and size are specified when the object is instantiated using
the Create method.
Create a button
fireEvent_0 = Button.Create("Print DateTime", 100, 23);
// button text, width and height
fireEvent_0.Location(25, 20); // located button on it's container from left from top
fireEvent_0.FlatStyle = FlatStyle.system; // prettiness
fireEvent_0.Click += onfireEvent_0Clicked; // method to run
eventFireControl.AddControl(fireEvent_0); // adds button to form
GDict_0 = GlobalDictionary.Create( true, Event_0_GDict_Name ) ; // GDict_0 corresponds to button_0
The magic starts here
December 17, 2012 25 Code Monkeys Drinking Delta Tea
This method runs … Method void onfireEvent_0Clicked (Object sender,
EventArgs args) Variables: string nowDateTime; Begin nowDateTime = DateToString
(ComputerDateTime) + " " + TimeToString(ComputerDateTime);
print(nowDateTime + " fireEvent_0_Trigger() Date Time Test");
fireEvent_0_Trigger(); End;
December 17, 2012 26 Code Monkeys Drinking Delta Tea
Method void putGDictStrValue (GlobalDictionary GDict, string keyVal, string strVal)
begin
GDict.Items[keyVal] = strVal;
end;
Method void putGDictIntValue (GlobalDictionary GDict, string keyVal, int
intVal) begin
GDict.Items[keyVal] = intVal;
end;
Method void fireEvent_0_Trigger()
begin { mark the work dictionary }
print("into trigger " + Event_0_GDict_Name + "count " + NumToStr(GDict_0.Count,0));
putGDictStrValue(GDict_0, "Trigger0", senderIndiName);
putGDictIntValue(GDict_0, "Trigger0Date", Currentdate);
putGDictIntValue(GDict_0, "Trigger0Time", Currenttime);
print("out of trigger " + Event_0_GDict_Name + "count " + NumToStr(GDict_0.Count,0));
End;
December 17, 2012 27 Code Monkeys Drinking Delta Tea
So, in the Levels drawing indicator, catch the event Method void wireToGD_trigger ()
// wires this indicator to changes to this GDict Begin GDict = GlobalDictionary.Create( true, GDict_Name ) ;
// if GDict is to be used between charts/applications, set to TRUE
GDict.ItemChanged += heyNewData; GDict.ItemAdded += heyNewData; end;
Yes, one more event handler Yes, it’s hooked in twice Yes, there's a story
December 17, 2012 28 Code Monkeys Drinking Delta Tea
Method void heyNewData(Object sender, ItemProcessedEventArgs someItem)
begin
// IF this method is called, an update event has fired, was caught here, and need to restart this indicator
print(DateToString (ComputerDateTime) + " " + TimeToString(ComputerDateTime) + " hey new data Levels");
Throw RecalculateException.Create();
end;
Throw this exception to force the recalculation and reploting of an analysis technique.
December 17, 2012 29 Code Monkeys Drinking Delta Tea
December 17, 2012 Code Monkeys Drinking Delta Tea 30
Setup Click
Handler
Setup GD Event
Handler
Button Click
Handler
GD Event Handler
Restart Indicator
Press the button
Write to GD
In Indicator
On Form
I want to thank Fari and his Team for hosting me here today.
Fari will have this powerPoint presentation as a .pdf
Feel free to contact me via email at ◦ [email protected]
Oh – the title! ◦ People who love to write code are referred to as code
monkeys ◦ There is a running gag in Fari’s Futures chat room about
drinking tea to calm down ◦ “delta tea” is a take off on the calculus term for infinitesimal
step widths, the so-called differentials, denoted by dt
▲ t
December 17, 2012 32 Code Monkeys Drinking Delta Tea
Follow this
This is Not part of the Presentation
December 17, 2012 Code Monkeys Drinking Delta Tea 33
A Vector is a special type of array.
◦ Each item in the Vector is referenced by an integer index, starting with '0'.
◦ It is dynamic (doesn't have a fixed size). ◦ Vectors have a 'front' which is position '0'. And a 'back' which is
the last position in the Vector. ◦ Vectors can contain normal datatypes (such as int, string, double,
bool) or other Classes. ◦ When a new item is inserted into a Vector, the index of all the
current items after that index are increased by one. ◦ When an item is erased from a Vector, the index of all the items
after that index are decreased by one. ◦ Vectors don't have a history, so you can't refer to a vector[1]
meaning one bar ago. This is an important difference from arrays.
https://community.tradestation.com/wiki/display/EasyLanguage/Vector+Class
December 17, 2012 34 Code Monkeys Drinking Delta Tea
Designed to bring data from a different symbol or bar interval into the current Chart or RadarScreen.
However, there are numerous limitations to its implementation, and in most cases it is inadvisable to use PSP.
Unless you have no other alternative, then they’re great.
December 17, 2012 35 Code Monkeys Drinking Delta Tea
A Price Series Provider provides data about a symbol at specified intervals.
◦
December 17, 2012 36 Code Monkeys Drinking Delta Tea
StreamReader Class ◦ Implements a class that reads characters from a
file.
StreamWriter Class ◦ Implements a class for writing data to a file.
December 17, 2012 37 Code Monkeys Drinking Delta Tea
Form Class ◦ Allows you to display a custom form window or
dialog in a TradeStation Indicator.
Button Class ◦ Displays a push button control within a container in
a form. A Click event is fired when the button is pressed.
◦ The name of the button and size are specified when the object is instantiated using the Create method.
December 17, 2012 38 Code Monkeys Drinking Delta Tea
The Global Dictionary allows you to set up a collection of key/value pairs that can be shared between EasyLanguage analysis techniques and strategies. …
There are two ways the Global Dictionary can be configured. … In the other, the Global Dictionary is configured to share with additional window types.
Elements are added to the global dictionary using the Add(sKey, oValue) method where sKey is a string containing the key name and oValue is the value to be stored.
Elements (key and value) are removed from the global dictionary using the Remove(sKey) method. The Contains(sKey) method is used to determine if an element key exists in the dictionary .
December 17, 2012 39 Code Monkeys Drinking Delta Tea
Go to every chart, and right click disable indicator, then right click enable indicator. ◦ That gets old fast with a lot of charts
Restart TradeStation, a very brute force disable / enable ◦ You’re not stressed 15 minutes before the open,
are you?
Push a button and restart all the indicators ◦ Even I can do that …
December 17, 2012 40 Code Monkeys Drinking Delta Tea
Value1 = cumuSumCurrent + Upticks + Downticks;
// accumulate the current session real time volu
if cumuSumHistory = 0 then cumuPct = 100 else
cumuPct = 100 * Value1 / cumuSumHistory;
If barAvg = 0 then nowPct = 100 else nowPct = 100
* (Upticks + Downticks) / barAvg;
December 17, 2012 41 Code Monkeys Drinking Delta Tea
// used to account for o/n to RTH / ramp up the HMA's from the open ... If time[0] >= RTHstartTime and Time[1] <= RTHstartTime then barCounter
= 1; barCounter = barCounter +1; getInternalsData(); getValueScores(); getSlopeScores(); sigRaw = getAvg(); plot41(sigRaw,"sigRaw",magenta, default, 1); sigHMA = rr_Hull_MA(sigRaw, minlist(barCounter, sigHMAlength)); plot42(sigHMA, "HMA", rr_PlotSlopeColor(sigHMA,Green, Red)); plot51(ctr,"ctr",white,default,0); plot52(ctr+hystCtr,"posHyst",white,default,0); plot53(ctr-hystCtr,"negHyst",white,default,0);
December 17, 2012 42 Code Monkeys Drinking Delta Tea