Exemple #1
0
    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
Exemple #2
0
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']))