Working on data handlers. Added Schema class for validation and Filter class to build querys

This commit is contained in:
Juan Pablo Amoroso
2019-05-28 18:24:34 -03:00
parent 5d1005d26e
commit 5a4085a816
3 changed files with 125 additions and 4 deletions
+2 -4
View File
@@ -1,4 +1,2 @@
from .datahandler import DataHandler
from .historic_datahandler import HistoricDataHandler
from .spx_datahandler import SPXDataHandler
from .balanced_datahandler import BalancedDataHandler
from .schema import *
from .historical_options_data import HistoricalOptionsData
@@ -0,0 +1,30 @@
import pandas as pd
from .schema import Schema
class HistoricalOptionsData:
"""Historical Options Data container class."""
def __init__(self, file, key=None, query=None, schema=None):
if schema:
assert isinstance(schema, Schema)
else:
schema = Schema.canonical()
schema.update({"contract": "optionroot", "date": "quotedate"})
self.schema = schema
self._data = pd.read_hdf(file, key=key, where=query)
columns = self._data.columns
assert all((col in columns for col in schema))
self._data["dte"] = (self._data["expiration"] -
self._data["quotedate"]).dt.days
def __getitem__(self, item):
return self._data[item]
def __setitem__(self, item, value):
self._data[item] = value
def __repr__(self):
return self._data.__repr__()
+93
View File
@@ -0,0 +1,93 @@
class Schema:
"""Data schema class (used to run validations)"""
columns = [
"underlying", "underlying_last", "date", "contract", "type",
"expiration", "strike", "bid", "ask"
]
def canonical():
"""Builder method that returns a `Schema` with default mappings"""
mappings = {key: key for key in Schema.columns}
return Schema(mappings)
def __init__(self, mappings):
assert all((key in mappings for key in Schema.columns))
self._mappings = mappings
def update(self, mappings):
self._mappings.update(mappings)
def __setitem__(self, key, value):
self._mappings[key] = value
def __getitem__(self, key):
return Field(key, self._mappings[key])
def __iter__(self):
return iter(self._mappings.values())
def __repr__(self):
return "Schema({})".format(
[Field(k, m) for k, m in self._mappings.items()])
class Field:
"""Encapsulates data fields to build filters used by strategies"""
def __init__(self, name, mapping):
self.name = name
self.mapping = mapping
def _create_filter(self, operator, value):
query = "{field} {op} {value}".format(field=self.mapping,
op=operator,
value=value)
return Filter(query)
def __lt__(self, value):
return self._create_filter("<", value)
def __le__(self, value):
return self._create_filter("<=", value)
def __gt__(self, value):
return self._create_filter(">", value)
def __ge__(self, value):
return self._create_filter(">=", value)
def __eq__(self, value):
return self._create_filter("==", value)
def __ne__(self, value):
return self._create_filter("!=", value)
def __repr__(self):
return "Field(name='{}', mapping='{}')".format(self.name, self.mapping)
class Filter:
"""This class determines entry/exit conditions for strategies"""
def __init__(self, query):
self.query = query
def _compose_filter(self, operator, other):
assert isinstance(other, Filter)
new_query = "({}) {} ({})".format(self.query, operator, other.query)
return Filter(query=new_query)
def __and__(self, other):
return self._compose_filter("&", other)
def __or__(self, other):
return self._compose_filter("|", other)
def __invert__(self):
return Filter("!({})".format(self.query))
def __repr__(self):
return "Filter(query='{}')".format(self.query)