mirror of
				https://github.com/bspeice/metrik
				synced 2025-11-03 18:00:51 -05:00 
			
		
		
		
	Initial Mongo refactoring work
This commit is contained in:
		
							
								
								
									
										29
									
								
								metrik/tasks/base.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								metrik/tasks/base.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					from __future__ import print_function
 | 
				
			||||||
 | 
					from luigi import Task
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from metrik.targets.mongo_target import MongoTarget
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MongoCreateTask(Task):
 | 
				
			||||||
 | 
					    def __init__(self, *args, **kwargs):
 | 
				
			||||||
 | 
					        super(MongoCreateTask, self).__init__(*args, **kwargs)
 | 
				
			||||||
 | 
					        self.mongo_id = hash(str(self.to_str_params()))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_collection_name(self):
 | 
				
			||||||
 | 
					        raise NotImplementedError('Please set the collection name.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def output(self):
 | 
				
			||||||
 | 
					        return MongoTarget(self.get_collection_name(), self.mongo_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def run(self):
 | 
				
			||||||
 | 
					        p_names = self.get_params()
 | 
				
			||||||
 | 
					        p_values = self.get_param_values(p_names, [], self.param_kwargs)
 | 
				
			||||||
 | 
					        print(p_values)
 | 
				
			||||||
 | 
					        data_dict = self.retrieve_data(**dict(p_values))
 | 
				
			||||||
 | 
					        data_dict['_id'] = self.mongo_id
 | 
				
			||||||
 | 
					        self.output().persist(data_dict)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @staticmethod
 | 
				
			||||||
 | 
					    def retrieve_data(self, *args, **kwargs):
 | 
				
			||||||
 | 
					        raise NotImplementedError('Get me some data!')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -12,7 +12,7 @@ from io import StringIO
 | 
				
			|||||||
from dateutil.parser import parse
 | 
					from dateutil.parser import parse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from metrik.targets.mongo_target import MongoTarget
 | 
					from metrik.targets.mongo_target import MongoTarget
 | 
				
			||||||
 | 
					from metrik.tasks.base import MongoCreateTask
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LiborRate = namedtuple('LiborRate', [
 | 
					LiborRate = namedtuple('LiborRate', [
 | 
				
			||||||
    'publication', 'overnight', 'one_week', 'one_month', 'two_month',
 | 
					    'publication', 'overnight', 'one_week', 'one_month', 'two_month',
 | 
				
			||||||
@ -20,18 +20,13 @@ LiborRate = namedtuple('LiborRate', [
 | 
				
			|||||||
])
 | 
					])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class LiborRateTask(Task):
 | 
					class LiborRateTask(MongoCreateTask):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    date = DateParameter()
 | 
					    date = DateParameter()
 | 
				
			||||||
    currency = Parameter()
 | 
					    currency = Parameter()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def output(self):
 | 
					    def get_collection_name(self):
 | 
				
			||||||
        h = hash(str(self.to_str_params()))
 | 
					        return 'libor'
 | 
				
			||||||
        return MongoTarget('libor', h)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def run(self):
 | 
					 | 
				
			||||||
        libor_record = self.retrieve_data(self.date, self.currency)
 | 
					 | 
				
			||||||
        self.output().persist(libor_record._asdict())
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @staticmethod
 | 
					    @staticmethod
 | 
				
			||||||
    def retrieve_data(date, currency):
 | 
					    def retrieve_data(date, currency):
 | 
				
			||||||
@ -46,7 +41,9 @@ class LiborRateTask(Task):
 | 
				
			|||||||
        text = requests.get(url).text
 | 
					        text = requests.get(url).text
 | 
				
			||||||
        f = StringIO(text)
 | 
					        f = StringIO(text)
 | 
				
			||||||
        next(f)  # Skip the header
 | 
					        next(f)  # Skip the header
 | 
				
			||||||
        record = {'currency': currency}
 | 
					
 | 
				
			||||||
 | 
					        # TODO: Messing with globals() is probably a terrible idea, is there
 | 
				
			||||||
 | 
					        # a better way to write the below code?
 | 
				
			||||||
        for row in csv.DictReader(f, fieldnames=fields):
 | 
					        for row in csv.DictReader(f, fieldnames=fields):
 | 
				
			||||||
            mapping = {
 | 
					            mapping = {
 | 
				
			||||||
                'Overnight': 'overnight',
 | 
					                'Overnight': 'overnight',
 | 
				
			||||||
@ -58,7 +55,8 @@ class LiborRateTask(Task):
 | 
				
			|||||||
                '1 Year': 'one_year'
 | 
					                '1 Year': 'one_year'
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if row['usd_ice_libor']:
 | 
					            if row['usd_ice_libor']:
 | 
				
			||||||
                record[mapping[row['tenor']]] = float(row['usd_ice_libor'])
 | 
					                globals()[mapping[row['tenor']]] = float(row['usd_ice_libor'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if row['publication']:
 | 
					            if row['publication']:
 | 
				
			||||||
                # Weird things happen with the publication field. For whatever reason,
 | 
					                # Weird things happen with the publication field. For whatever reason,
 | 
				
			||||||
                # the *time* is correct, but very often the date gets screwed up.
 | 
					                # the *time* is correct, but very often the date gets screwed up.
 | 
				
			||||||
@ -66,6 +64,19 @@ class LiborRateTask(Task):
 | 
				
			|||||||
                # download with `requests`, I see both date (often incorrect) and time.
 | 
					                # download with `requests`, I see both date (often incorrect) and time.
 | 
				
			||||||
                dt = parse(row['publication'])
 | 
					                dt = parse(row['publication'])
 | 
				
			||||||
                dt = dt.replace(year=date.year, month=date.month, day=date.day)
 | 
					                dt = dt.replace(year=date.year, month=date.month, day=date.day)
 | 
				
			||||||
                record['publication'] = dt
 | 
					                globals()['publication'] = dt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return LiborRate(**record)
 | 
					        # Because of the shenanigans I did earlier with locals(), ignore
 | 
				
			||||||
 | 
					        # unresolved references. Probably a better way to do this.
 | 
				
			||||||
 | 
					        # noinspection PyUnresolvedReferences
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					            'currency': currency,
 | 
				
			||||||
 | 
					            'publication': publication,
 | 
				
			||||||
 | 
					            'overnight': overnight,
 | 
				
			||||||
 | 
					            'one_week': one_week,
 | 
				
			||||||
 | 
					            'one_month': one_month,
 | 
				
			||||||
 | 
					            'two_month': two_month,
 | 
				
			||||||
 | 
					            'three_month': three_month,
 | 
				
			||||||
 | 
					            'six_month': six_month,
 | 
				
			||||||
 | 
					            'one_year': one_year
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -8,42 +8,39 @@ from metrik.conf import USER_AGENT
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# noinspection PyUnresolvedReferences
 | 
					# noinspection PyUnresolvedReferences
 | 
				
			||||||
class TestICE(TestCase):
 | 
					class TestICE(TestCase):
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_correct_libor_Aug8_2016(self):
 | 
					    def test_correct_libor_Aug8_2016(self):
 | 
				
			||||||
        # Validate with:
 | 
					        # Validate with:
 | 
				
			||||||
        # https://www.theice.com/marketdata/reports/icebenchmarkadmin/ICELiborHistoricalRates.shtml?excelExport=&criteria.reportDate=8%2F8%2F16&criteria.currencyCode=USD
 | 
					        # https://www.theice.com/marketdata/reports/icebenchmarkadmin/ICELiborHistoricalRates.shtml?excelExport=&criteria.reportDate=8%2F8%2F16&criteria.currencyCode=USD
 | 
				
			||||||
        aug8_libor = LiborRateTask.retrieve_data(datetime(2016, 8, 8), 'USD')
 | 
					        aug8_libor = LiborRateTask.retrieve_data(datetime(2016, 8, 8), 'USD')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert aug8_libor.overnight == .4189
 | 
					        assert aug8_libor['overnight'] == .4189
 | 
				
			||||||
        assert aug8_libor.one_week == .4431
 | 
					        assert aug8_libor['one_week'] == .4431
 | 
				
			||||||
        assert aug8_libor.one_month == .5119
 | 
					        assert aug8_libor['one_month'] == .5119
 | 
				
			||||||
        assert aug8_libor.two_month == .6268
 | 
					        assert aug8_libor['two_month'] == .6268
 | 
				
			||||||
        assert aug8_libor.three_month == .8065
 | 
					        assert aug8_libor['three_month'] == .8065
 | 
				
			||||||
        assert aug8_libor.six_month == 1.1852
 | 
					        assert aug8_libor['six_month'] == 1.1852
 | 
				
			||||||
        assert aug8_libor.one_year == 1.5081
 | 
					        assert aug8_libor['one_year'] == 1.5081
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        london_tz = pytz.timezone('Europe/London')
 | 
					        london_tz = pytz.timezone('Europe/London')
 | 
				
			||||||
        actual = london_tz.localize(datetime(2016, 8, 8, 11, 45, 6))
 | 
					        actual = london_tz.localize(datetime(2016, 8, 8, 11, 45, 6))
 | 
				
			||||||
        assert aug8_libor.publication == actual
 | 
					        assert aug8_libor['publication'] == actual
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_correct_libor_Aug9_2010(self):
 | 
					    def test_correct_libor_Aug9_2010(self):
 | 
				
			||||||
        # Validate with:
 | 
					        # Validate with:
 | 
				
			||||||
        # https://www.theice.com/marketdata/reports/icebenchmarkadmin/ICELiborHistoricalRates.shtml?excelExport=&criteria.reportDate=8%2F9%2F10&criteria.currencyCode=USD
 | 
					        # https://www.theice.com/marketdata/reports/icebenchmarkadmin/ICELiborHistoricalRates.shtml?excelExport=&criteria.reportDate=8%2F9%2F10&criteria.currencyCode=USD
 | 
				
			||||||
        aug9_libor = LiborRateTask.retrieve_data(datetime(2010, 8, 9), 'USD')
 | 
					        aug9_libor = LiborRateTask.retrieve_data(datetime(2010, 8, 9), 'USD')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert aug9_libor.overnight == .23656
 | 
					        assert aug9_libor['overnight'] == .23656
 | 
				
			||||||
        assert aug9_libor.one_week == .27725
 | 
					        assert aug9_libor['one_week'] == .27725
 | 
				
			||||||
        assert aug9_libor.one_month == .29
 | 
					        assert aug9_libor['one_month'] == .29
 | 
				
			||||||
        assert aug9_libor.two_month == .3375
 | 
					        assert aug9_libor['two_month'] == .3375
 | 
				
			||||||
        assert aug9_libor.three_month == .40438
 | 
					        assert aug9_libor['three_month'] == .40438
 | 
				
			||||||
        assert aug9_libor.six_month == .6275
 | 
					        assert aug9_libor['six_month'] == .6275
 | 
				
			||||||
        assert aug9_libor.one_year == .995
 | 
					        assert aug9_libor['one_year'] == .995
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        london_tz = pytz.timezone('Europe/London')
 | 
					        london_tz = pytz.timezone('Europe/London')
 | 
				
			||||||
        actual = london_tz.localize(datetime(2010, 8, 9, 15, 49, 12))
 | 
					        actual = london_tz.localize(datetime(2010, 8, 9, 15, 49, 12))
 | 
				
			||||||
        assert aug9_libor.publication == actual
 | 
					        assert aug9_libor['publication'] == actual
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_correct_date_reasoning(self):
 | 
					    def test_correct_date_reasoning(self):
 | 
				
			||||||
        # Make sure I document how to handle datetime issues in the future
 | 
					        # Make sure I document how to handle datetime issues in the future
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user