Similarity: 60.2744%
Last active
August 29, 2015 14:04
-
-
Save film42/e400aee59ff97a795522 to your computer and use it in GitHub Desktop.
(WIP) Pattern Matching Algorithm using Stock Tick Data: Uses FooPlot for Rendering Graphs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <vector> | |
#include <fstream> | |
#include <string> | |
#include <cmath> | |
#include "functional.h" | |
#include "graph.h" | |
// DATA PARSING | |
#define PATTERN_DISTANCE 30 | |
typedef std::vector< long long > DateVector; | |
typedef std::vector< long double > DataVector; | |
typedef std::vector< DataVector > PatternVector; | |
struct DataSet { | |
DataSet( long long approx_size = 0 ) { | |
date_times.reserve( approx_size ); | |
bid_prices.reserve( approx_size ); | |
asking_prices.reserve( approx_size ); | |
} | |
DateVector date_times; | |
DataVector bid_prices; | |
DataVector asking_prices; | |
DataVector average_prices() { | |
// Cached? | |
if( !m_average_prices.empty() ) return m_average_prices; | |
// Make | |
m_average_prices.reserve( bid_prices.size() ); | |
for( int i = 0; i < bid_prices.size(); ++i ) { | |
auto average = ( bid_prices[i] + asking_prices[i] ) / 2; | |
m_average_prices.push_back( average ); | |
} | |
return m_average_prices; | |
} | |
private: | |
DataVector m_average_prices; | |
}; | |
DataSet parse_file( std::string path, long long approximate_size = 0 ) { | |
DataSet data_set( approximate_size ); | |
std::ifstream file( path ); | |
std::string buffer; | |
while( std::getline(file, buffer) ) { | |
// First 14 is for date | |
auto date = buffer.substr( 0, 14 ); | |
// Reset the buffer | |
buffer = buffer.substr( 15 ); | |
size_t index = buffer.find(','); | |
// Get data points | |
auto data_point_1 = buffer.substr( 0, index ); | |
auto data_point_2 = buffer.substr( index + 1 ); | |
// Save the data points | |
data_set.date_times.push_back( std::stoll( date ) ); | |
data_set.bid_prices.push_back( std::stod( data_point_1 ) ); | |
data_set.asking_prices.push_back( std::stod( data_point_2 ) ); | |
} | |
return data_set; | |
} | |
// ALGORITHM | |
long double percent_change( long double start, long double current ) { | |
// Refactor me!! | |
try { | |
long double result = ( ( current - start ) / ( std::fabs(start) ) ) * 100; | |
if( result == 0 ) return 0.0000001; | |
else return result; | |
} catch(...) { | |
return 0.0000001; | |
} | |
} | |
PatternVector pattern_storage( DataVector average_line ) { | |
PatternVector all_patterns; | |
long long y = PATTERN_DISTANCE; | |
long long x = average_line.size() - (2 * PATTERN_DISTANCE); | |
while( y < x ) { | |
DataVector pattern; | |
// Save All Patterns | |
for( int i = ( PATTERN_DISTANCE - 1 ); i >= 0; --i ) { | |
auto index = y - PATTERN_DISTANCE; | |
auto point = percent_change( average_line[ index ] , average_line[y - i] ); | |
pattern.push_back( point ); | |
} | |
all_patterns.push_back( pattern ); | |
// Outcome Range and Current Point | |
DataVector outcome_range; | |
long long end_range = y + PATTERN_DISTANCE; | |
long long i = ( y + 20 ); | |
for( ; i < end_range; ++i) { | |
outcome_range.push_back( average_line[i] ); | |
} | |
long double current_point = average_line[y]; | |
// Average Outcome | |
auto fn_outcome_range = Functional< DataVector >( outcome_range ); | |
auto average_outcome = fn_outcome_range.average(); | |
// Future Outcome | |
auto future_outcome = percent_change( current_point , average_outcome ); | |
// FINISH ME! | |
++y; // Inc | |
} | |
return all_patterns; | |
} | |
DataVector current_pattern( DataVector average_line ) { | |
DataVector pattern; | |
pattern.reserve( PATTERN_DISTANCE ); | |
for( int i = (PATTERN_DISTANCE - 1); i >= 0; --i ) { | |
auto result = percent_change( average_line[ PATTERN_DISTANCE ], average_line[i] ); | |
pattern.push_back( result ); | |
} | |
return pattern; | |
} | |
void pattern_recognition( PatternVector pattern_vec, DataVector current_pattern ) { | |
for( auto& pattern : pattern_vec ) { | |
long double similarity_total = 0; | |
for( int i = 0; i < PATTERN_DISTANCE; ++i ) { | |
long double _change = percent_change( pattern[i], current_pattern[i] ); | |
similarity_total += ( 100 - std::fabs( _change ) ); | |
} | |
long double similarity_average = similarity_total / PATTERN_DISTANCE; | |
if( similarity_average > 60 ) { | |
std::cout << "Similarity: " << similarity_average << "%" << std::endl; | |
Graph< DataVector > graph; | |
graph.add_line( pattern, "FF0000" ); | |
graph.add_line( current_pattern, "001DAD" ); | |
std::cout << graph.to_fooplot() << std::endl; | |
} | |
} | |
} | |
// TESTER | |
int main(int argc, const char * argv[]) { | |
std::cout << "Start" << std::endl; | |
auto data_set = parse_file( "/tmp/GBPUSD/GBPUSD1d.txt", 1000 ); | |
std::cout << "Done" << std::endl; | |
// Just do it (TM) | |
auto average_line = data_set.average_prices(); | |
auto patterns = pattern_storage( average_line ); | |
auto current = current_pattern( average_line ); | |
pattern_recognition( patterns, current ); | |
// insert code here... | |
std::cout << "Hello, World!\n"; | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <functional> | |
#include <vector> | |
template< typename T > | |
class Functional { | |
public: | |
typedef typename T::value_type V; | |
Functional( T collection ): m_collection(collection) {} | |
V sum() { | |
V total = 0; | |
for( auto val : m_collection ) { | |
total += val; | |
} | |
return total; | |
} | |
V average() { | |
return sum() / m_collection.size(); | |
} | |
private: | |
T m_collection; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <vector> | |
#include <sstream> | |
#include "base64.h" | |
template< class T > | |
class Graph { | |
public: | |
Graph() {} | |
void add_line( T data_points, std::string color = "000000" ) { | |
std::ostringstream outstream; | |
outstream << "{\"type\":3,\"eq\":["; | |
for(int i = 0; i < data_points.size(); ++i) { | |
// Json comma | |
if( i > 0 ) { | |
outstream << ","; | |
} | |
// Point | |
outstream << "[\"" << (i+1) << "\",\"" << data_points[i] << "\"]"; | |
} | |
outstream << "]"; | |
outstream << ",\"color\":\"#" << color << "\"}"; | |
m_chart_lines.push_back( outstream.str() ); | |
} | |
std::string to_json() { | |
std::ostringstream outstream; | |
outstream << "["; | |
for( auto line : m_chart_lines ) { | |
outstream << line << ","; | |
} | |
outstream << "{\"type\":1000,\"window\":[\"2.427692307692307\",\"31.427692307692304\",\"-0.01092341430854167\",\"0.008419398805292345\"]}]"; | |
return outstream.str(); | |
} | |
std::string to_fooplot() { | |
std::string json = to_json(); | |
auto b64_input_json = reinterpret_cast<const unsigned char*>( json.c_str() ); | |
auto b64_encoded_json = base64_encode( b64_input_json , (unsigned int) json.length() ); | |
std::ostringstream outstream; | |
outstream << "http://fooplot.com/#"; | |
outstream << b64_encoded_json; | |
return outstream.str(); | |
} | |
private: | |
std::vector< std::string > m_chart_lines; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Source: https://github.com/ReneNyffenegger/development_misc/tree/master/base64 | |
// Only change: | |
while((i++ < 3)) | |
ret += '='; | |
// Becomes | |
while((i++ < 3)) | |
ret += '-'; | |
// To match the fooplot b64 encoder |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Data available here: http://sentdex.com/GBPUSD.zip