Tired of Manipulating Arrays – Try a Vector and a Queue
Vectors:
An array like structure but are dynamic and have a plethora of tools at your disposal. Arrays are cool and can be multi-dimensional and can be easily manipulated. But they require a lot of forethought as to how much size to reserve for their implementation. Now don’t think this is going to be an advanced EasyLanguage tutorial, because it’s really not. Most of us TRS-80, Ti-99/4A, Vic-20 and Commodore 64 trained programmers of the early ’80s have not welcomed objects with open arms and that is really a mistake. In this sense we are like cavemen – we have all of the rudimentary tools at our disposal and can create some really cool stuff and we can really understand what we are doing. With time and effort, we can get to the same place as object-oriented programmers. We just don’t like the concept of using other’s tools as much as we like using ours. So if you aren’t classically trained in programming you may have an advantage when tieing into the objects of a programming language. This little tutorial is a very brief glimpse into a whole different world of programming. The beauty is you can combine “old school” programming with objects – even if you don’t understand how the objects are truly constructed. I want to introduce the concept of the Vector and the Queue- truly cool Swiss Army knives. First the vector. Let’s just jump into some of the code – it really is simple.
Object Instantiation – a long word for declaring variable:
Using elsystem.collections;
Vars: Vector opVector(NULL),
Vector hiVector(Null),
Vector loVector(Null),
Vector clVector(Null),
Vector barVector(Null),
Queue timeStampQue(Null);
Once
Begin
barVector = new Vector;
opVector = new Vector;
hiVector = new Vector;
loVector = new Vector;
clVector = new Vector;
timeStampQue = new Queue;
end;
Instantiating and Declaring Vectors and Queue
You have to tell EasyLanguage you want to use some of the tools in the elsystem.collections. You do this by simply tell it you are Using elsystem.collections. The word collections is a catch-all for a bunch of different types of data structures. Remember data structures are just programming constructs used to hold data – like an array. All the variables that you declare in EasyLanguage are arrays – you just aren’t really aware of it. When you index into them to get prior values then you become slightly aware of it. In this portion of code, I create five vectors and one queue and assign them the Null or an empty value. I just finished a programming gig where I had to build dynamically sized bars from the base data. Kind of like creating 15, 30, 60-minute bars from a 5-minute bar chart or stream. I did this using arrays because I wanted to be able to index into them to go back in time and I didn’t how far I wanted to go back. So I declared some arrays with large dimensions to be safe. This really takes a bite out of your resources which costs space and time. I had played with Vector like objects in Python, so I thought I would post about them here and show how cool they are. Remember this is a rudimentary program and could be streamlined and cleaned up. Each vector will store their respective time, open, high, low and close values of the combined bar. In a later post, I would like to do this with a Dictionary. So the opVector will hold the open price, the hiVector will hold the high price and so on.
Build a Queue – why the extra ue?
I want to build 15-minute bars from 5-minute bars so I need to know when to sample the data to properly collect the corresponding data. If I start at 9:30 then I want to sample the data at 9:45 and look back three bars to get the open and the highest high and the lowest low. The close will simply be the close of the 9:45 bar. I want to do this at 9:45, 10:00. 10:15 and so on. I could manipulate the time and use the modulus function to see if the minutes are multiples of 15 and I tried this but it didn’t work too well. So I thought since I was already in the collections why not build a list or a queue with all the timestamps I would need. This is how I did it.
vars: hrs(0),mins(0),barMult(3),combBarTimeInterval(0),totBarsInHour(0),startTime(930),endTime(1615),cnt(0);
Once
Begin
mins = fracPortion(t/100);
combBarTimeInterval = barInterval*barMult;
While value1 < endTime
Begin
cnt = cnt + 1;
Value1 = calcTime(startTime,cnt*combBarTimeInterval);
// print("Inside queue : ",Value1," ",cnt*combBarTimeInterval);
timeStampQue.Enqueue(Value1);
end;
end;
Populating A Queue With Time Stamps
I simply use the CalcTime function to add 15-minute intervals to the start time and then I add them to the queue: timeStampQue.Enqueue(Value1); You access the methods or tools to a class by using the dot (” . “) notation. Once I instantiated or created the timeStampQue I gained access to all the tools that belong to that object. The Enqueue method simply appends the list the value that you pass it. I would have preferred the method to be labeled simply add. How did I figure out the right method name you ask? I accessed the Dictionary from the View menu in the TDE. Here is a picture to help:
Dictionary:
I use the keyword Once to just execute the code one time. You could have said if BarNumber = 1, but why not use the tools at your disposal, I figured out the combBarTimeInterval by using the 5-minute bar multiplier (3). I then looped from startTime to endTime in 15-minute intervals and stored the timeStamps in the queue. So every time stamp I need is in the timeStampQue. All I need now is to compare the time of the 5-minute bar to the time stamps inside the queue. This is where using object really come in handy.
Queue Methods:
Old school would have looped through all of the elements in the list and compared them to the value I was seeking and if found it would return true. In the object world, I can simply ask the object itself to see if the value is in it:
condition1 = timeStampQue.Contains(t);
Cool! If condition1 is true then I know I am sitting on the 5-minute bar that shares the same timestamp as a 15-minute bar. If the time stamps are the same then I can start building the large timeframe from the lower timeframe. You add elements to a vector by using the insert method. I simply looked it up in the dictionary. I had to specify where to insert the value in the vector. I simply inserted each value into the [0] location. Remember we are inserting so everything else in the vector is moved down.
Vector Methods:
If condition1 then
Begin
barVector.insert(0,t);
opVector.insert(0,open[2]);
hiVector.insert(0,highest(h[0],3));
loVector.insert(0,lowest(l[0],3));
clVector.insert(0,close[0]);
end;
Inserting Values at Vector Location 0
I only need to keep track of the last 10 15-minute bars, so once the vector count exceeded 10, I simply popped off the value at the back end – pop_back(). I figured this out by looking at Martin Whittaker’s awesome website – www.markplex.com.
If opVector.Count > 10 then
begin
barVector.pop_back();
opVector.pop_back();
hiVector.pop_back();
loVector.pop_back();
clVector.pop_back();
end;
Popping the Back-End
To check my work I printed the 15-minute bars on each 5-minute bar to make sure the bars were being built properly. These data structures expect an object to be inserted, added, popped so when you print out one of their values you have to tell the print statement what the object should be translated as. Here the keyword asType comes into play. Take a look at my code, and you will see what I mean. I hope this gets you excited about objects because the collections class can save you a ton of time and is really cool. Use it and you can brag that you are an OOP programmer at your next cocktail party.
Code Listing:
Using elsystem.collections;
Vars: Vector opVector(NULL),
Vector hiVector(Null),
Vector loVector(Null),
Vector clVector(Null),
Vector barVector(Null),
Queue timeStampQue(Null);
Once
Begin
barVector = new Vector;
opVector = new Vector;
hiVector = new Vector;
loVector = new Vector;
clVector = new Vector;
timeStampQue = new Queue;
end;
vars: hrs(0),mins(0),barMult(3),combBarTimeInterval(0),totBarsInHour(0),startTime(930),endTime(1615),cnt(0);
Once
Begin
mins = fracPortion(t/100);
combBarTimeInterval = barInterval*barMult;
While value1 < endTime
Begin
cnt = cnt + 1;
Value1 = calcTime(startTime,cnt*combBarTimeInterval);
// print("Inside queue : ",Value1," ",cnt*combBarTimeInterval);
timeStampQue.Enqueue(Value1);
end;
end;
condition1 = timeStampQue.Contains(t);
Print(d," ",t," ",condition1);
If condition1 then
Begin
barVector.insert(0,t);
opVector.insert(0,open[2]);
hiVector.insert(0,highest(h[0],3));
loVector.insert(0,lowest(l[0],3));
clVector.insert(0,close[0]);
end;
If opVector.Count > 10 then
begin
barVector.pop_back();
opVector.pop_back();
hiVector.pop_back();
loVector.pop_back();
clVector.pop_back();
end;
vars:vectCnt(0);
print(d," ",t);
If opVector.Count > 9 then
Begin
For vectCnt = 0 to 9
begin
print(vectCnt," ",barVector.at(vectCnt) astype int," ",opVector.at(vectCnt) astype double," ",hiVector.at(vectCnt) astype double," ",loVector.at(vectCnt) astype double," ",clVector.at(vectCnt) astype double);
end;
end;
Program in its Entirety