예제 #1
0
    def post(self, color: int):
        millis, ts = utils.get_utc_timestamp()

        msgs = []
        success = False
        return_code = 403

        dim = constants.CANVAS_DIMENSION

        batch = fs.initializeBatch()

        cells = []
        for row in range(dim):
            for col in range(dim):
                cell_id = 'row{}col{}'.format(row, col)
                cell_data = {'updated': millis, 'value': color}

                fs.updateMatrixCellBatched(batch, cell_id, cell_data)
                cells.append(cell_data)

        fs.commitBatch(batch)

        success = True

        response_obj = {'timestamp': millis, 'msgs': msgs, 'success': success}

        if success:
            return_code = 200

        return response_obj, return_code
예제 #2
0
    def get(self, row: int):
        millis, ts = utils.get_utc_timestamp()

        msgs = []
        success = False
        return_code = 403

        matrix = fs.getMatrix(row)
        if matrix is not None:
            indicators = []
            for cell in matrix:
                indicators.append(cell)

            success = True

        response_obj = {'timestamp': millis,
                        'msgs': msgs,
                        'success': success}

        if success:
            return_code = 200
            response_obj.update({
                'matrix': indicators
            })

        return response_obj, return_code
def update_participant(event):
    """
    Update a participant's name and/or url

    :param event: Lambda event containing the API Gateway request body including updated name or url and the
    path parameters wheel_id and participant_id
    {
      "pathParameters":
      {
        "wheel_id": string ID of the wheel (DDB Hash Key)
        "participant_id": string ID of the participant (DDB Hash Key)
      },
      "body":
      {
        "id": string ID of the participant (DDB Hash Key),
        "name": string name of the wheel (optional),
        "url: Valid URL for the participant (optional),
      }
    }
    :return: response dictionary containing the updated participant object if successful
    {
      "body":
      {
        "id": string ID of the participant (DDB Hash Key),
        "wheel_id": string ID of the wheel (DDB Hash Key),
        "name": string name of the wheel,
        "url: URL for the participant,
        "created_at": creation timestamp,
        "updated_at": updated timestamp,
      }
    }
    """
    wheel_id = event['pathParameters']['wheel_id']
    participant_id = event['pathParameters']['participant_id']
    # Check that the participant exists
    participant = WheelParticipant.get_existing_item(Key={
        'id': participant_id,
        'wheel_id': wheel_id
    })
    body = event['body']
    params = {'updated_at': get_utc_timestamp()}
    if not check_string(body.get('name', 'Not Specified')) or not check_string(
            body.get('url', 'Not Specified')):
        raise base.BadRequestError(
            "Participants names and urls must be at least 1 character in length"
        )

    if 'name' in body:
        params['name'] = body['name']

    if 'url' in body:
        params['url'] = body['url']

    WheelParticipant.update_item(Key={
        'id': participant_id,
        'wheel_id': wheel_id
    },
                                 **to_update_kwargs(params))
    participant.update(params)
    return participant
예제 #4
0
 def create_genesis_block(self):
     """
     A function to generate genesis block and appends it to the chain.
     The block has index 0, previous_hash as 0, and a valid hash.
     """
     genesis_block = Block(0, [], get_utc_timestamp(), "0")
     self.proof_of_work(genesis_block)
     self.chain.append(genesis_block.__str__())
def create_participant(event):
    """
    Create a participant

    :param event: Lambda event containing the API Gateway request body including a name and a url and the
    path parameter wheel_id
    {
      "pathParameters":
      {
        "wheel_id": string ID of the wheel (DDB Hash Key)
      },
      "body":
      {
        "name": participant name string,
        "url: Valid URL for the participant,
      }
    }
    :return: response dictionary containing new participant object if successful
    {
      "body":
      {
        "id": string ID of the participant (DDB Hash Key),
        "wheel_id": string ID of the wheel (DDB Hash Key),
        "name": string name of the wheel,
        "url: URL for the participant,
        "created_at": creation timestamp,
        "updated_at": updated timestamp,
      }
    }
    """
    wheel_id = event['pathParameters']['wheel_id']
    body = event['body']
    if not check_string(body.get('name', None)) or not check_string(
            body.get('url', None)):
        raise base.BadRequestError(
            "Participants require a name and url which must be at least 1 character in length"
        )

    wheel = Wheel.get_existing_item(Key={'id': wheel_id})
    create_timestamp = get_utc_timestamp()

    participant = {
        'wheel_id': wheel_id,
        'id': get_uuid(),
        'name': body['name'],
        'url': body['url'],
        'created_at': create_timestamp,
        'updated_at': create_timestamp,
    }
    with choice_algorithm.wrap_participant_creation(wheel, participant):
        WheelParticipant.put_item(Item=participant)
    return participant
예제 #6
0
def root():
    millis, ts = utils.get_utc_timestamp()

    msgs = []
    success = False
    return_code = 403

    msgs.append('forbidden')

    response_obj = {'timestamp': millis, 'msgs': msgs, 'success': success}

    response = jsonify(response_obj)
    return response, return_code
예제 #7
0
    def post(self):
        millis, ts = utils.get_utc_timestamp()

        msgs = []
        success = False
        return_code = 403

        dim = 5

        batch = fs.initializeBatch()

        order_to_be_read = 0
        cells = []
        for row in range(dim):
            for col in range(dim):
                cell_id = 'row{}col{}'.format(row, col)
                cell_data = {
                    'created': millis,
                    'updated': millis,
                    'id': cell_id,
                    'position': order_to_be_read,
                    'row': row,
                    'col': col,
                    'value': 0
                }

                fs.setMatrixCellBatched(batch, cell_id, cell_data)
                cells.append(cell_data)

                order_to_be_read += 1

        fs.commitBatch(batch)

        success = True

        response_obj = {'timestamp': millis,
                        'msgs': msgs,
                        'success': success}

        if success:
            return_code = 200
            response_obj.update({
                'matrix': cells
            })

        return response_obj, return_code
예제 #8
0
def send_message():
    try:
        if request.method == 'GET':
            return render_template('./sendmessage.html', title="Send Message")
        elif request.method == 'POST':
            values = request.form

            # Check that the required fields are in the POST'ed data
            required = ['sender', 'private_key', 'message']
            if not all(values[k] != "" for k in required):
                return 'Missing values', 400

            sender = values['sender']
            sender_private_key = values['private_key']

            user = users.get_user(sender)
            if user == "Username does not exist":
                return user, 400
            sender_public_key = user['public_key']

            msg = Message(user["username"], user['name'], values["message"],
                          get_utc_timestamp())

            # Create a new Transaction
            signature = blockchain.sign_transaction(sender_private_key,
                                                    msg.__str__())
            if len(signature) == 2:
                return signature[0], 400
            transaction_result = blockchain.submit_transaction(
                sender, sender_public_key, msg.__str__(), signature)

            if not transaction_result:
                return 'Invalid Transaction!', 406
            else:
                response = {
                    'message':
                    'Transaction will be added to Block ' +
                    str(transaction_result),
                    'signature':
                    signature
                }
                return jsonify(response), 200
    except Exception as e:
        return "Error in format", 400
예제 #9
0
def update_wheel(event):
    """
    Update the name of the wheel and/or refresh its participant count

    :param event: Lambda event containing the API Gateway request path parameter wheel_id
    {
      "pathParameters":
      {
        "wheel_id": string ID of the wheel (DDB Hash Key)
      },
      "body":
      {
        "id": string ID of the wheel (DDB Hash Key),
        "name": string name of the wheel,
      }
    }
    :return: response dictionary containing the updated wheel object if successful
    {
      "body":
      {
        "id": string ID of the wheel (DDB Hash Key),
        "name": string name of the wheel,
        "participant_count": number of participants in the wheel,
        "created_at": creation timestamp,
        "updated_at": updated timestamp,
      }
    }
    """
    wheel_id = event['pathParameters']['wheel_id']
    key = {'id': wheel_id}
    # Make sure wheel exists
    wheel = Wheel.get_existing_item(Key=key)
    name = event['body'].get('name', None)
    if not check_string(name):
        raise base.BadRequestError(
            "Updating a wheel requires a new name of at least 1 character in length"
        )

    update = {'name': name, 'updated_at': get_utc_timestamp()}
    Wheel.update_item(Key=key, **to_update_kwargs(update))
    # Represent the change locally for successful responses
    wheel.update(update)
    return wheel
예제 #10
0
    def mine(self):
        """
        This function serves as an interface to add the pending
        transactions to the blockchain by adding them to the block
        and figuring out Proof Of Work.
        """
        if not self.unconfirmed_transactions:
            return False

        last_block = json.loads(self.last_block)

        new_block = Block(index=last_block['index'] + 1,
                          transactions=self.unconfirmed_transactions,
                          timestamp=get_utc_timestamp(),
                          previous_hash=Block.compute_hash(last_block))
        proof = self.proof_of_work(new_block)
        self.add_block(new_block, proof)

        self.unconfirmed_transactions = []
        return new_block.index
예제 #11
0
    def post(self, row: int, col: int, color: int):
        millis, ts = utils.get_utc_timestamp()

        msgs = []
        success = False
        return_code = 403

        time.sleep(constants.DELAY_IN_SECS)

        cell_id = 'row{}col{}'.format(row, col)
        cell_data = {'updated': millis, 'value': color}
        fs.updateMatrixCell(cell_id, cell_data)

        success = True

        response_obj = {'timestamp': millis, 'msgs': msgs, 'success': success}

        if success:
            return_code = 200

        return response_obj, return_code
예제 #12
0
    def submit_transaction(self, sender_username, sender_address, data,
                           signature):
        """
        Add a transaction to transactions array if the signature verified
        """

        transaction = OrderedDict({
            'sender_username': sender_username,
            'sender_address': sender_address,
            'data': data,
            'timestamp': get_utc_timestamp()
        })

        transaction_verification = self.verify_transaction_signature(
            sender_address, signature, data)

        if transaction_verification:
            self.unconfirmed_transactions.append(transaction)
            return len(self.chain) + 1
        else:
            return False
예제 #13
0
def create_wheel(event):
    """
    Create a wheel. Requires a name

    :param event: Lambda event containing the API Gateway request body including a name
    {
      "body":
      {
        "name": string wheel name,
      }
    }
    :return: response dictionary containing new wheel object if successful
    {
      "body":
      {
        "id": string ID of the wheel (DDB Hash Key),
        "name": string name of the wheel,
        "participant_count": number of participants in the wheel,
        "created_at": creation timestamp,
        "updated_at": updated timestamp,
      }
    }
    """
    create_timestamp = get_utc_timestamp()
    body = event['body']
    if body is None or not check_string(body.get('name', None)):
        raise base.BadRequestError(
            f"New wheels require a name that must be a string with a length of at least 1.  Got: {body}"
        )

    wheel = {
        'id': get_uuid(),
        'name': body['name'],
        'created_at': create_timestamp,
        'updated_at': create_timestamp,
    }
    with choice_algorithm.wrap_wheel_creation(wheel):
        Wheel.put_item(Item=wheel)
    return wheel
예제 #14
0
def plot_rolling_returns(returns, factor_returns=None,  live_start_date=None,
                         cone_std=None, legend_loc='best', volatility_match=False,
                         cone_function=ts_metrics.forecast_cone_bootstrap, ax=None, **kwargs):
    """
    Plots cumulative rolling returns versus some benchmarks'.
    Backtest returns are in green, and out-of-sample (live trading)
    returns are in red.
    Additionally, a non-parametric cone plot may be added to the
    out-of-sample returns region.
    Parameters
    ----------
    returns : pd.Series
        Daily returns of the strategy, noncumulative.
    factor_returns : pd.Series, optional
        Daily noncumulative returns of a risk factor.
         - This is in the same style as returns.
    live_start_date : datetime, optional
        The date when the strategy began live trading, after
        its backtest period. This date should be normalized.
    cone_std : float, or tuple, optional
        If float, The standard deviation to use for the cone plots.
        If tuple, Tuple of standard deviation values to use for the cone plots
         - See timeseries.forecast_cone_bounds for more details.
    legend_loc : matplotlib.loc, optional
        The location of the legend on the plot.
    volatility_match : bool, optional
        Whether to normalize the volatility of the returns to those of the
        benchmark returns. This helps compare strategies with different
        volatilities. Requires passing of benchmark_rets.
    cone_function : function, optional
        Function to use when generating forecast probability cone.
        The function signiture must follow the form:
        def cone(in_sample_returns (pd.Series),
                 days_to_project_forward (int),
                 cone_std= (float, or tuple),
                 starting_value= (int, or float))
        See ts_metrics.forecast_cone_bootstrap for an example.
    ax : matplotlib.Axes, optional
        Axes upon which to plot.
    **kwargs, optional
        Passed to plotting function.
    Returns
    -------
    ax : matplotlib.Axes
        The axes that were plotted on.
"""
    if ax is None:
        ax = plt.gca()

    if volatility_match and factor_returns is None:
        raise ValueError('volatility_match requires passing of'
                         'factor_returns.')
    elif volatility_match and factor_returns is not None:
        bmark_vol = factor_returns.loc[returns.index].std()
        returns = (returns / returns.std()) * bmark_vol

    cum_rets = ts_metrics.cum_returns(returns, 1.0)


    y_axis_formatter = FuncFormatter(utils.one_dec_places)
    ax.yaxis.set_major_formatter(FuncFormatter(y_axis_formatter))

    if factor_returns is not None:
        cum_factor_returns = ts_metrics.cum_returns( factor_returns[cum_rets.index], 1.0)
        cum_factor_returns.plot(lw=2, color='gray', label=factor_returns.name, alpha=0.60,
                                ax=ax, **kwargs)

    if live_start_date is not None:
        live_start_date = utils.get_utc_timestamp(live_start_date)
        is_cum_returns = cum_rets.loc[cum_rets.index < live_start_date]
        oos_cum_returns = cum_rets.loc[cum_rets.index >= live_start_date]
    else:
        is_cum_returns = cum_rets
        oos_cum_returns = pd.Series([])

    is_cum_returns.plot(lw=3, color='forestgreen', alpha=0.6, label='Backtest', ax=ax, **kwargs)

    if len(oos_cum_returns) > 0:
        oos_cum_returns.plot(lw=4, color='red', alpha=0.6, label='Live', ax=ax, **kwargs)

        if cone_std is not None:
            if isinstance(cone_std, (float, int)):
                cone_std = [cone_std]

            is_returns = returns.loc[returns.index < live_start_date]
            cone_bounds = cone_function( is_returns,len(oos_cum_returns),
                                        cone_std=cone_std, starting_value=is_cum_returns[-1])

            cone_bounds = cone_bounds.set_index(oos_cum_returns.index)

            for std in cone_std:
                ax.fill_between(cone_bounds.index,
                                cone_bounds[float(std)],
                                cone_bounds[float(-std)],
                                color='steelblue', alpha=0.5)
    if legend_loc is not None:
        ax.legend(loc=legend_loc)
    ax.axhline(1.0, linestyle='--', color='black', lw=2)
    ax.set_ylabel('Cumulative returns')
    ax.set_xlabel('')
    return ax
예제 #15
0
    def post(self):
        millis, ts = utils.get_utc_timestamp()

        msgs = []
        success = False
        return_code = 403

        body = request.json
        if body is not None and 'paint' in body:
            colors = []

            start_painting_at = body[
                'start_painting_at'] if 'start_painting_at' in body else 0
            start_posteffects_at = body[
                'start_posteffects_at'] if 'start_posteffects_at' in body else 0
            next_posteffect_at = body[
                'next_posteffect_at'] if 'next_posteffect_at' in body else 0
            unreliable = body['unreliable'] if 'unreliable' in body else None
            unreliable_prob = body[
                'unreliable_probability'] if 'unreliable_probability' in body else None
            unreliable_fill = body[
                'unreliable_fill'] if 'unreliable_fill' in body else None

            if 'fill' in body:
                payload = {'action': 'fill', 'value': body['fill']}
                if unreliable_fill is not None:
                    payload.update({
                        'unreliable': unreliable_fill,
                        'probability': unreliable_prob
                    })
                utils.postCloudTask(constants.PAINTER_QUEUE,
                                    '/matrix/task',
                                    payload=payload,
                                    start_in=0)

            cells = body['paint']
            for row, cols in enumerate(cells):
                for col, value in enumerate(cols):
                    colors.append(value)

                    if 'delay' in body:
                        delay = body['delay']
                    else:
                        delay = constants.DELAY_IN_SECS

                    payload = {
                        'action': 'paint',
                        'row': row,
                        'col': col,
                        'value': value
                    }
                    if unreliable is not None:
                        payload.update({
                            'unreliable': unreliable,
                            'probability': unreliable_prob
                        })
                    if delay > 0:
                        utils.postCloudTask(
                            constants.PAINTER_QUEUE,
                            '/matrix/delayedtask/{}'.format(delay),
                            payload=payload,
                            start_in=start_painting_at)
                    else:
                        utils.postCloudTask(constants.PAINTER_QUEUE,
                                            '/matrix/task',
                                            payload=payload,
                                            start_in=start_painting_at)

            if 'posteffects' in body:
                start_at = start_posteffects_at
                posteffects = body['posteffects']
                for effect in posteffects:
                    payload = {'action': 'posteffect', 'effect': effect}
                    utils.postCloudTask(constants.PAINTER_QUEUE,
                                        '/matrix/task',
                                        payload=payload,
                                        start_in=start_at)

                    start_at += next_posteffect_at

            success = True

        response_obj = {'timestamp': millis, 'msgs': msgs, 'success': success}

        if success:
            return_code = 200
            response_obj.update({'colors': colors})

        return response_obj, return_code
예제 #16
0
    def post(self, **kwargs):
        millis, ts = utils.get_utc_timestamp()

        msgs = []
        success = False
        return_code = 403

        if 'delay' in kwargs:
            delay = kwargs['delay']
            msg = 'applying a delay of {}s'.format(delay)
            logging.warning(msg)
            msgs.append(msg)
            time.sleep(delay)

        payload = request.get_data(as_text=True) or None
        if payload is not None:
            payload = json.loads(payload)

            # print(payload)

            action = payload['action']
            probability = 100 - payload[
                'probability'] if 'probability' in payload else constants.DEFAULT_PROBABILITY
            if probability > 100:
                probability = 100
            if probability < 0:
                probability = 0
            unreliable = random.randint(
                0, 100) > probability if 'unreliable' in payload and payload[
                    'unreliable'] else False
            label = '?' if unreliable else ''

            if unreliable:
                msg = '{} UNRELIABLE'.format(action)
                logging.warning(msg)
                msgs.append(msg)

            if action == 'posteffect' and payload['effect'] == 'b&w':
                dim = constants.CANVAS_DIMENSION
                matrix = fs.getMatrixAll()
                if matrix is not None:
                    batch = fs.initializeBatch()
                    cells = []
                    for row in range(dim):
                        for col in range(dim):
                            #   TODO: use position!
                            color = matrix[dim * row + col]['value']

                            if color >= 0:
                                if unreliable:
                                    color = constants.LUT_LENGTH - color
                                    if color == 5:
                                        color = 4  #   due to inverse of 5 being 5
                                color += 100

                                cell_id = 'row{}col{}'.format(row, col)
                                cell_data = {
                                    'updated': millis,
                                    'label': label,
                                    'value': color
                                }

                                fs.updateMatrixCellBatched(
                                    batch, cell_id, cell_data)
                            cells.append(cell_data)
                    fs.commitBatch(batch)

                    success = True
                else:
                    msg = 'matrix is null'
                    logging.error(msg)
                    msgs.append(msg)

            if (action
                    == 'invert_fill') or (action == 'posteffect'
                                          and payload['effect'] == 'invert'):
                dim = constants.CANVAS_DIMENSION
                matrix = fs.getMatrixAll()
                if matrix is not None:
                    batch = fs.initializeBatch()
                    cells = []
                    for row in range(dim):
                        for col in range(dim):
                            #   TODO: use position!
                            color = matrix[dim * row + col]['value']

                            if color >= 0:
                                color = constants.LUT_LENGTH - color
                                if unreliable:
                                    color = constants.LUT_LENGTH - color
                                    if color == 5:
                                        color = 4  #   due to inverse of 5 being 5

                                cell_id = 'row{}col{}'.format(row, col)
                                cell_data = {
                                    'updated': millis,
                                    'label': label,
                                    'value': color
                                }

                                fs.updateMatrixCellBatched(
                                    batch, cell_id, cell_data)
                            cells.append(cell_data)
                    fs.commitBatch(batch)

                    success = True
                else:
                    msg = 'matrix is null'
                    logging.error(msg)
                    msgs.append(msg)

            if action == 'fill':
                color = payload['value']
                if color >= 0 and unreliable:
                    color = constants.LUT_LENGTH - color
                    if color == 5:
                        color = 4  #   due to inverse of 5 being 5

                dim = constants.CANVAS_DIMENSION
                batch = fs.initializeBatch()
                cells = []
                for row in range(dim):
                    for col in range(dim):
                        if color >= 0:
                            cell_id = 'row{}col{}'.format(row, col)
                            cell_data = {
                                'updated': millis,
                                'label': label,
                                'value': color
                            }

                            fs.updateMatrixCellBatched(batch, cell_id,
                                                       cell_data)
                        cells.append(cell_data)
                fs.commitBatch(batch)

                success = True

            if action == 'paint':
                color = payload['value']

                row = payload['row']
                col = payload['col']

                if color >= 0:
                    if unreliable:
                        color = constants.LUT_LENGTH - color
                        if color == 5:
                            color = 4  #   due to inverse of 5 being 5

                    cell_id = 'row{}col{}'.format(row, col)
                    cell_data = {
                        'updated': millis,
                        'label': label,
                        'value': color
                    }
                    fs.updateMatrixCell(cell_id, cell_data)

                    print('{} -> {}'.format(cell_id, color))

                success = True

            if action == 'invert':
                row = payload['row']
                col = payload['col']

                cell = fs.getMatrixByCoords(row, col)
                if cell is not None:
                    color = cell[0]['value']

                    if color >= 0:
                        color = constants.LUT_LENGTH - color
                        if unreliable:
                            color = constants.LUT_LENGTH - color

                        cell_id = 'row{}col{}'.format(row, col)
                        cell_data = {
                            'updated': millis,
                            'label': label,
                            'value': color
                        }
                        fs.updateMatrixCell(cell_id, cell_data)

                    success = True

                else:
                    msg = 'unable to read cell at {},{}'.format(row, col)
                    logging.error(msg)
                    msgs.append(msg)

        response_obj = {'timestamp': millis, 'msgs': msgs, 'success': success}

        if success:
            return_code = 200

            if unreliable:
                return_code = 404

        return response_obj, return_code