def login(self, email=settings.QUANTOPIAN_EMAIL, password=settings.QUANTOPIAN_PWD): if self.is_authenticated: raise AlreadyLoggedIn() response = self.get(build_url('signin')) form_candidates = response.soup.select("form#new_user") if len(form_candidates) != 1: raise RequestError('failed to get login form', response) login_form = form_candidates[0] login_form.select("#user_email")[0]['value'] = email login_form.select("#user_password")[0]['value'] = password response = self.submit(login_form, build_url(login_form.attrs['action'])) if not response.ok: raise RequestError('failed to submit login form', response) # Check authentication worked by accessing the account response = self.get(build_url('account'), allow_redirects=False) if not response.ok: raise RequestError('failed to verify the user is authenticated', response) # If not logged in the requests is redirected to the login page if response.is_redirect: return False self.is_authenticated = True return True
def lookup_sid(sid): """Lookup a security by id. >>> lookup_sid(45149) {u'symbol': u'HTBX', u'name': u'HEAT BIOLOGICS INC', u'sid': 45149} >>> lookup_sid(1111111) # Returns None of no security is found :param sid: Security id. :type sid: int :return: A dictionary containing the security's name, sid, and symbol or ``None`` if no security is found. :rtype: dict :raises quantopian_tools.exceptions.RequestError: If the request to the quantopian_tools server failed. :raises quantopian_tools.exceptions.ResponseValidationError: If the response from the quantopian_tools server is not of the format expected. """ url = build_url('securities/', q=sid) headers = { 'x-csrf-token': session.browser.get_csrf_token(build_url('algorithms')), 'x-requested-with': 'XMLHttpRequest' } response = session.browser.get(url, headers=headers) if not response.ok: raise RequestError('failed to lookup sid %d' % sid, response) valid, data_or_errors = schema.validate(response.json(), { "data": schema.dictionary( required=True, nullable=False, schema={ "matches": schema.list_( required=True, nullable=True, coerce='falsey_to_none', schema=schema.dictionary( schema={ 'name': schema.string( required=True, nullable=False, empty=False), 'sid': schema.integer( required=True, nullable=False, min=1), 'symbol': schema.string( required=True, nullable=False, empty=False) })) }) }, allow_unknown=True) if not valid: raise ResponseValidationError('GET', url, None, data_or_errors) for security in data_or_errors['data']['matches'] or []: if security['sid'] == sid: return security return None
def delete_algorithm(algorithm): url = build_url('algorithms', 'delete') headers = { 'x-csrf-token': session.browser.get_csrf_token(build_url('algorithms')), 'x-requested-with': 'XMLHttpRequest' } data = {'ids[]': algorithm['id']} response = session.browser.post(url, data=data, headers=headers) return response.ok
def get_algorithm_ids(): response = session.browser.get(build_url('algorithms')) if not response.ok: raise RequestError('failed to get algorithm ids', response) rows = response.soup.find_all( 'tr', attrs={'data-algo-id': re.compile(r'^[a-fA-F\d]{24}$')}) return [row.attrs['data-algo-id'] for row in rows]
def validate_algorithm(algorithm, start_date=None, end_date=None, data_frequency='minute'): assert session.browser.is_authenticated, "You must be authenticated to validate algorithms" url = build_url('algorithms', algorithm['id'], 'validate') data = { 'code': algorithm['code'], 'algo_id': algorithm['id'], 'data_frequency': data_frequency, 'start_date_str': start_date.strftime('%m/%d/%Y'), 'end_date_str': end_date.strftime('%m/%d/%Y') } headers = { 'x-csrf-token': session.browser.get_csrf_token(build_url('algorithms', algorithm['id'])), 'x-requested-with': 'XMLHttpRequest' } response = session.browser.post(url, data=data, headers=headers) if not response.ok: raise RequestError('validate algorithm request failed', response) valid, data_or_errors = schema.validate(response.json(), { "data": schema.dictionary( required=True, schema={ "test_results": schema.list_( required=True, schema=schema.dictionary(schema={ "passed": schema.boolean(required=True, nullable=False) })) }) }, allow_unknown=True) if not valid: raise ResponseValidationError('POST', url, data, data_or_errors) test_results = data_or_errors['data']['test_results'] return all(result['passed'] for result in test_results), test_results
def save_algorithm(algorithm): url = build_url('algorithms', algorithm['id'], 'autosave') headers = { 'x-csrf-token': session.browser.get_csrf_token(build_url('algorithms', algorithm['id'])), 'x-requested-with': 'XMLHttpRequest' } response = session.browser.post(url, data=algorithm, headers=headers) if not response.ok: raise RequestError('failed to save algorithm %s' % algorithm['id'], response) valid, data_or_errors = schema.validate( response.json(), {"status": schema.string(required=True, nullable=False)}, allow_unknown=True) if not valid: raise ResponseValidationError('POST', url, algorithm, data_or_errors) return data_or_errors['status'].lower() == 'ok'
def new_algorithm(title): url = build_url('algorithms') headers = { 'x-csrf-token': session.browser.get_csrf_token(build_url('algorithms')), 'x-requested-with': 'XMLHttpRequest' } data = {'title': title} response = session.browser.post(url, data=data, headers=headers) if not response.ok: raise RequestError('failed to create a new algorithm', response) valid, data_or_errors = schema.validate(response.json(), { "to": schema.string(required=True, nullable=False, regex=r'^/algorithms/[a-fA-F\d]{24}$') }, allow_unknown=True) if not valid: raise ResponseValidationError('POST', url, data, data_or_errors) return data_or_errors['to'].lower().replace('/algorithms/', '')
def get_algorithm(algorithm_id): response = session.browser.get(build_url('algorithms', algorithm_id)) if not response.ok: raise RequestError('failed to get algorithm %s' % algorithm_id, response) title = response.soup.find(lambda tag: 'value' in tag.attrs, attrs={'name': 'algorithm[title]'}) code = response.soup.find(attrs={'name': 'algorithm[code]'}) if not title or not code: if not response.ok: raise RequestError( 'failed to find code and title for algorithm %s' % algorithm_id, response) return { 'id': algorithm_id, 'title': title.attrs['value'], 'code': code.text.lstrip() }
def run_backtest(algorithm, start_date, end_date, capital_base, data_frequency='minute'): url = build_url('backtests', 'start_ide_backtest') headers = { 'x-csrf-token': session.browser.get_csrf_token(build_url('algorithms', algorithm['id'])), 'x-requested-with': 'XMLHttpRequest' } data = { 'algo_id': algorithm['id'], 'code': algorithm['code'], 'backtest_start_date_year': start_date.year, 'backtest_start_date_month': start_date.month, 'backtest_start_date_day': start_date.day, 'backtest_end_date_year': end_date.year, 'backtest_end_date_month': end_date.month, 'backtest_end_date_day': end_date.day, 'backtest_capital_base': capital_base, 'backtest_data_frequency_value': data_frequency } response = session.browser.post(url, data=data, headers=headers) if not response.ok: raise RequestError('failed to start backtest', response) valid, data_or_errors = schema.validate(response.json(), { "data": schema.dictionary( required=True, schema={ "ws_open_msg": schema.string(required=True, nullable=False, empty=False), "ws_url": schema.string(required=True, nullable=False, empty=False) }) }, allow_unknown=True) if not valid: raise ResponseValidationError('POST', url, algorithm, data_or_errors) with closing(websocket.create_connection( data_or_errors['data']['ws_url'])) as ws: ws.send( json.dumps({ 'e': 'open', 'p': { 'a': data_or_errors['data']['ws_open_msg'], 'cursor': 0, 'include_txn': True } })) while True: msg = json.loads(ws.recv()) if msg['e'] == 'log': yield schema.validate(msg['p'], log_payload_schema(), raise_exc=True) elif msg['e'] == 'performance': yield schema.validate(msg['p'], performance_payload_schema(), raise_exc=True) elif msg['e'] == 'risk_report': yield schema.validate(msg['p'], risk_report_payload_schema(), raise_exc=True) elif msg['e'] == 'done': yield schema.validate(msg['p'], done_payload_schema(), raise_exc=True) break elif msg['e'] == 'exception': exc = schema.validate(msg['p'], exception_payload_schema(), raise_exc=True) trace = '\n'.join(" File \"{}\", line {}, in {}\n {}" "".format(s['filename'], s['lineno'], s['method'], s['line']) for s in exc['stack']) raise RuntimeError( "Traceback (most recent call last):\n{}\n{}: {}" "".format(trace, exc['name'], exc['message'])) else: raise QuantopianException("unknown backtest event '{}'".format( msg['e']))