42
TS OOP Tools and Toys December 17, 2012 December 17, 2012 1 Code Monkeys Drinking Delta Tea

TS OOP Tools and Toys December 17, 2012 - Hamzei Analytics

  • Upload
    others

  • View
    3

  • Download
    0

Embed Size (px)

Citation preview

TS OOP Tools and Toys

December 17, 2012

December 17, 2012 1 Code Monkeys Drinking Delta Tea

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

December 17, 2012 10 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

December 17, 2012 21 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

December 17, 2012 Code Monkeys Drinking Delta Tea 31

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