mirror of
https://github.com/wassname/options_backtester.git
synced 2026-09-12 12:40:22 +08:00
Working on data handlers. Added Schema class for validation and Filter class to build querys
This commit is contained in:
@@ -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__()
|
||||
@@ -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)
|
||||
Reference in New Issue
Block a user