Using The Hash Table
Now that we have created an empty Hash Table and the Hash Index it is now time to start filling the table up with the appropriate information. As I pointed out in my last post, every day of any given year can be represented by a nine character string. If January 1st lands on a Tuesday, you can express this day with the following string, “1stTueJan.” That is if you want to ignore the year and in this case, we do.
Mapping Into the Hash Table
The table has already been prepared as well as the index. All we have to do is map the current day into the index. The location of the index value in the Hash Index array will then be used to locate the day’s location in the Hash Table. We will use a function to convert the current day of the year into a value our Hash Index can interpret.
Here is the code to the function. Don’t fret too much at the number of lines of code!
inputs: testDate(numericSeries);
vars: testMonth(0),tempStr("");
Array : prefixStrArr[6](""),dayofweekStr[5](""),monthName[12]("");
vars: monCnt(0),tueCnt(0),wedCnt(0),thuCnt(0),friCnt(0),tempDate1(0),tempDate2(0);
vars: freshStart(false),occurString(""),dayString(""),monthString("");
vars: whatOccurOfMonthStr(""),cnt(0),td(0),myCnt(0),daysBack(0);
preFixStrArr[1] = "1st";
preFixStrArr[2] = "2nd";
preFixStrArr[3] = "3rd";
preFixStrArr[4] = "4th";
preFixStrArr[5] = "5th";
preFixStrArr[6] = "6th";
dayOfWeekStr[1] = "Mon";
dayOfWeekStr[2] = "Tue";
dayOfWeekStr[3] = "Wed";
dayofWeekStr[4] = "Thu";
dayOfWeekStr[5] = "Fri";
monthName[1] = "Jan";
monthName[2] = "Feb";
monthName[3] = "Mar";
monthName[4] = "Apr";
monthName[5] = "May";
monthName[6] = "Jun";
monthName[7] = "Jul";
monthName[8] = "Aug";
monthName[9] = "Sep";
monthName[10] = "Oct";
monthName[11] = "Nov";
monthName[12] = "Dec";
tempDate1 = month(testDate[0]);
tempDate2 = month(testDate[1]);
cnt = 0;monCnt = 0;tueCnt=0;wedCnt=0;thuCnt=0;friCnt=0;
While (month(date) = month(date[cnt])) and cnt < 30
Begin
// print(date," ",date[cnt]," ",cnt);
cnt = cnt + 1;
end;
daysBack = cnt -1;
If daysBack < 0 then daysBack = 0;
For cnt = daysBack downto 0
begin
If dayOfWeek(date[cnt]) = 1 then monCnt = monCnt + 1;
If dayOfWeek(date[cnt]) = 2 then tueCnt = tueCnt + 1;
If dayOfWeek(date[cnt]) = 3 then wedCnt = wedCnt + 1;
If dayOfWeek(date[cnt]) = 4 then thuCnt = thuCnt + 1;
If dayOfWeek(date[cnt]) = 5 then friCnt = friCnt + 1;
end;
//print("counts: ",monCnt," ",tueCnt," ",wedCnt," ",thuCnt," ",friCnt);
If dayOfWeek(date) = Monday then tempStr = preFixStrArr[monCnt];
If dayOfWeek(date) = Tuesday then tempStr = preFixStrArr[tueCnt];
If dayOfWeek(date) = Wednesday then tempStr = preFixStrArr[wedCnt];
If dayOfWeek(date) = Thursday then tempStr = preFixStrArr[thuCnt];
If dayOfWeek(date) = Friday then tempStr = preFixStrArr[friCnt];
tempStr = tempStr + dayOfWeekStr[dayOfWeek(date)];
tempStr = tempStr + monthName[month(date)];
GetWhichWeekMonth = tempStr;
GetWhichWeekMonth Function
Here is where using an integer representation of the date would reduce the number of lines of code tremendously. Well, I made my bed I might as well sleep in it. You will see some duplication between this code and the Hash Table creator function. I have to store names for the week rank, day of the week, and month in arrays. There isn’t a simple function that will pull the week rank from any given date. So I simply take the date and work my way back to the beginning of the month counting each weekday as I go along.
For cnt = daysBack downto 0
begin
If dayOfWeek(date[cnt]) = 1 then monCnt = monCnt + 1;
If dayOfWeek(date[cnt]) = 2 then tueCnt = tueCnt + 1;
If dayOfWeek(date[cnt]) = 3 then wedCnt = wedCnt + 1;
If dayOfWeek(date[cnt]) = 4 then thuCnt = thuCnt + 1;
If dayOfWeek(date[cnt]) = 5 then friCnt = friCnt + 1;
end;
Getting The Hash Index
The number that is stored in the individual counters (monCnt, tueCnt, etc.) determines which week of the month the current day is located. I build the string through concatenation. First I get the week rank (“1st”, “2nd”, “3rd”, “4th”, “5th”), add the name of the day and then add the month. The end result looks like “1stMonJan”. From here I cross-reference the Hash Index and pull out the location of the of the string (aka index.) Here is the function GetHashIndex.
input: hashIndex[n](stringArrayRef),hashTableRows(numericSimple),searchString(string);
vars: iCnt(0),done(false);
GetHashIndex = 0;
done = false;
For iCnt = 1 to hashTableRows
Begin
// print("Looking for: ",searchString," ",hashIndex[iCnt]," ",iCnt);
If searchString = hashIndex[iCnt] then
begin
done = true;
GetHashIndex = iCnt;
end;
If done then break;
end;
GetHashIndex
As you can see it is a linear search that returns the Hash Index’s Index. Check out how I prematurely exit the loop by using the keyword Break. This keyword knocks you out of any loop where it is located. If you have a nested loop, the break only gets you out of that current loop where it is located.
Hast Table Indicator
Now how can we pull all this together to create a useful trading tool. I used these tools to create an indicator that plots the average daily change from one day to the next. So, if today is the “3rdMonJune” and the indicator reads 0.52, this represents that over the last X years the average percentage change is a plus .5%. Would it make sense to buy the “2ndFriJun” and exit on the close of the “3rdMonJune?” Maybe.
Here is the code for the Hash Table indicator.
vars: returnValString(""),iCnt(0),jCnt(0);
array: weekDayMonthIndex[300]("");
array: HashTable[300,100](0);
array: timeLine[300](0);
vars: searchString(""),numYearsCollected(0),hashIndex(0);
vars: yCnt(0),numYears(0);
vars: hashRows(300);
vars: myBarCount(0),maxNumYearsInHash(0),avgDailyChange(0),dailyChangeSum(0);
If barNumber = 1 then //build the hash index - index form "1stMonJul" "2ndFriDec"
begin
Value1 = HashIndexCreator(weekDayMonthIndex);
end;
numYearsCollected = HashTableCreator(HashTable,weekDayMonthIndex); {Build hash table as we go along}
If year(date) <> year(date[1]) then numYears = numYears + 1;
If numYearsCollected > 3 then // only pull information if there is at least three years of data
Begin
searchString = GetWhichWeekMonth(date); // convert today's date into a compatible Hash Index value
hashIndex = GetHashIndex(weekDayMonthIndex,hashRows,searchString); // find the location of today's value in the Hash Index
dailyChangeSum = 0;;
// print(d," ",searchString," ",hashIndex);
For yCnt = 2 to numYearsCollected
Begin
dailyChangeSum = dailyChangeSum + HashTable[hashIndex,yCnt];
end;
avgDailyChange = dailyChangeSum/numYearsCollected;
if year(date) = 116 then print(d," ",searchString," ",numYearsCollected," ",avgDailyChange);
if numYearsCollected > numYears-1 then plot1(avgDailyChange,"AvgChgFromYesterday");
End;
HashTableIndicator
Results of Using the Hash Table
Here is a simple output of the results from the indicator for the year of 2016. I sorted the data based on highest average daily change and number of years collected.
1160729 |
5thFriJul |
7 |
0.95 |
1161031 |
5thMonOct |
5 |
0.62 |
1160115 |
2ndFriJan |
16 |
0.56 |
1160830 |
5thTueAug |
7 |
0.55 |
1160713 |
2ndWedJul |
17 |
0.52 |
1160812 |
2ndFriAug |
17 |
0.52 |
1160519 |
3rdThuMay |
16 |
0.43 |
1161003 |
1stMonOct |
17 |
0.38 |
1160112 |
2ndTueJan |
16 |
0.38 |
1160223 |
4thTueFeb |
16 |
0.38 |
1161122 |
4thTueNov |
16 |
0.37 |
1160804 |
1stThuAug |
17 |
0.35 |
1160316 |
3rdWedMar |
16 |
0.35 |
1160711 |
1stMonJul |
17 |
0.34 |
1161121 |
3rdMonNov |
17 |
0.34 |
1160225 |
4thThuFeb |
16 |
0.34 |
1160517 |
3rdTueMay |
16 |
0.34 |
1160610 |
2ndFriJun |
16 |
0.34 |
1161215 |
3rdThuDec |
17 |
0.33 |
It looks like the buying the close “4thThuJul” is the way to go! But since there are only seven observations I think would think twice. But, buying the close on the day prior to “2ndFriJan” might offer that technical advantage you’re looking for.