def update_asset(managed_portfolio: portfolio.Portfolio,
                 managed_asset: asset.Asset,
                 asset_name: Optional[Text] = None,
                 asset_price: Optional[float] = None,
                 asset_currency: Optional[Text] = None) -> asset.Asset:
    """Updates an asset information.

  Args:
    managed_asset: Asset to update.
    asset_name: New name of the asset.
    asset_price: Price of the asset.
    asset_currency: Currency of the asset price.

  Returns:
    Asset updated.
  """
    if asset_name and asset_name != managed_asset.name:
        managed_asset.name = asset_name
    if asset_price and asset_price != managed_asset.current_price:
        managed_asset.current_price = asset_price
    if asset_currency and asset_currency != managed_asset.currency:
        managed_asset.currency = asset_currency

    portfolio_manager.store_portfolio(managed_portfolio)

    return managed_asset
Example #2
0
def get_account_info(client):
    """Get user's balance info."""
    assets = []
    total = 0
    response = client.query_private('Balance', {})
    balance = response.get('result')
    if not balance:
        from app import sentry
        sentry.captureMessage(response.get('error'))
        return None, None

    # TODO:
    # Collect all paris used in balance and query them once together.
    pair_list = [asset + 'ZUSD' for asset in balance.keys() if asset[0] == 'X']
    response = client.query_public('Ticker', {'pair': ','.join(pair_list)})
    pair_price = response.get('result')
    print(response)
    for asset in balance.keys():
        if asset[0] == 'X':
            pair_name = asset + 'ZUSD'
            new_asset = Asset(asset, float(balance.get(asset)),
                              float(pair_price.get(pair_name).get('c')[0]))
        else:
            new_asset = Asset(asset,
                              amount=float(balance.get(asset)),
                              total=float(balance.get(asset)))
        assets.append(new_asset.to_dict())
        total += new_asset.total
    return assets, total
def update_asset_stats(managed_asset: asset.Asset) -> stats.AssetStats:
    """Updates stats of given assets.

  Args:
    managed_asset: Asset for which to update stats.

  Returns:
    Stats of the given asset.
  """
    tracker = managed_asset.get_tracker()
    price = managed_asset.current_price

    if not tracker:
        return stats.StockStats(managed_asset=managed_asset, price=price)

    try:
        fetched_price = _parse_and_format_value(
            stock_info.get_live_price(tracker))
    except AssertionError:
        fetched_price = None

    if not fetched_price:
        return stats.StockStats(managed_asset=managed_asset, price=price)

    price = fetched_price
    managed_asset.current_price = price

    stock_data = stock_info.get_stats(tracker)
    if stock_data.empty:
        return stats.StockStats(managed_asset=managed_asset, price=price)

    try:  # TODO: handle all types of assets instead of only stocks.
        stock_stats = stats.StockStats(
            managed_asset=managed_asset,
            price=price,
            debt_to_equity=_get_stock_stat_value(
                stock_data, StockAttribute.DEBT_TO_EQUITY),
            dividend_yield=_get_stock_stat_value(
                stock_data, StockAttribute.DIVIDEND_YIELD),
            eps=_get_stock_stat_value(stock_data, StockAttribute.EPS),
            pe=_get_stock_stat_value(stock_data, StockAttribute.PE),
            profit_margin=_get_stock_stat_value(stock_data,
                                                StockAttribute.PROFIT_MARGIN),
            return_on_equity=_get_stock_stat_value(
                stock_data, StockAttribute.RETURN_ON_EQUITY),
            revenue_growth=_get_stock_stat_value(
                stock_data, StockAttribute.REVENUE_GROWTH),
            value_over_ebitda=_get_stock_stat_value(
                stock_data, StockAttribute.VALUE_OVER_EBITDA),
        )
        managed_asset.stats = stock_stats
        return stock_stats
    except Exception:
        return stats.StockStats(managed_asset=managed_asset, price=price)
Example #4
0
    def test_normal_scenario_with_two_users(self):
        # First create some users
        user1 = User.create_user(self.session, 'user1', 'abcd')
        user2 = User.create_user(self.session, 'user2', 'abcd')

        # Make sure user1 has 1 BTC for later deposit into a futures contract
        btc = Asset.create_asset('BTC')
        user1.increase_volume_of_asset(self.session, btc, Decimal('1'))

        # Create a futures contract worth 1 BTC in +14 days
        contract, asset = FuturesContract.create_contract(
            self.session, user1,
            datetime.now() + timedelta(days=14), btc, Decimal('1'), 'FUTURE',
            Decimal('100'))
        # This will fail if user1 has insufficient funds (i.e. < 1 BTC)
        assert contract is not None
        assert asset is not None
        self.session.commit()

        # Create an order for this contract (i.e. newly created asset)
        usd = Asset.create_asset('USD')
        ask_order = Order.create_order(self.session, user1, Decimal('20'), usd,
                                       contract, Decimal('50'), False,
                                       OrderType.limit_order.value)
        # Make sure we have enough funds
        assert ask_order is not None
        self.session.commit()

        # Put order into market
        assert put_order(self.session, ask_order) is None

        # Create a bid order from user2
        user2.increase_volume_of_asset(self.session, usd, Decimal('20'))
        bid_order1 = Order.create_order(self.session, user2, Decimal('20'),
                                        usd, contract, Decimal('50'), True,
                                        OrderType.limit_order.value)
        # Make sure we have enough funds
        assert bid_order1 is not None

        transaction = put_order(self.session, bid_order1)
        assert isinstance(transaction, Transaction)
        assert transaction.ask_order is ask_order
        assert transaction.bid_order is bid_order1

        contract.expire(self.session)
        assert user1.volume_of_asset(self.session, btc) == Decimal('0.5')
        assert user2.volume_of_asset(self.session, btc) == Decimal('0.5')

        # Run it again. Must be idempotent.
        contract.expire(self.session)
        assert user1.volume_of_asset(self.session, btc) == Decimal('0.5')
        assert user2.volume_of_asset(self.session, btc) == Decimal('0.5')
Example #5
0
    def test_normal_scenario_with_two_users(self):
        # First create some users
        user1 = User.create_user(self.session, "user1", "abcd")
        user2 = User.create_user(self.session, "user2", "abcd")

        # Make sure user1 has 1 BTC for later deposit into a futures contract
        btc = Asset.create_asset("BTC")
        user1.increase_volume_of_asset(self.session, btc, Decimal("1"))

        # Create a futures contract worth 1 BTC in +14 days
        contract, asset = FuturesContract.create_contract(
            self.session, user1, datetime.now() + timedelta(days=14), btc, Decimal("1"), "FUTURE", Decimal("100")
        )
        # This will fail if user1 has insufficient funds (i.e. < 1 BTC)
        assert contract is not None
        assert asset is not None
        self.session.commit()

        # Create an order for this contract (i.e. newly created asset)
        usd = Asset.create_asset("USD")
        ask_order = Order.create_order(
            self.session, user1, Decimal("20"), usd, contract, Decimal("50"), False, OrderType.limit_order.value
        )
        # Make sure we have enough funds
        assert ask_order is not None
        self.session.commit()

        # Put order into market
        assert put_order(self.session, ask_order) is None

        # Create a bid order from user2
        user2.increase_volume_of_asset(self.session, usd, Decimal("20"))
        bid_order1 = Order.create_order(
            self.session, user2, Decimal("20"), usd, contract, Decimal("50"), True, OrderType.limit_order.value
        )
        # Make sure we have enough funds
        assert bid_order1 is not None

        transaction = put_order(self.session, bid_order1)
        assert isinstance(transaction, Transaction)
        assert transaction.ask_order is ask_order
        assert transaction.bid_order is bid_order1

        contract.expire(self.session)
        assert user1.volume_of_asset(self.session, btc) == Decimal("0.5")
        assert user2.volume_of_asset(self.session, btc) == Decimal("0.5")

        # Run it again. Must be idempotent.
        contract.expire(self.session)
        assert user1.volume_of_asset(self.session, btc) == Decimal("0.5")
        assert user2.volume_of_asset(self.session, btc) == Decimal("0.5")
Example #6
0
 def subscribe_asset(self, symbol, exchange, secType):
     asset_key = f"{symbol}@{exchange}"
     self.assetCache[asset_key] = Asset(symbol=symbol,
                                        exchange=exchange,
                                        secType=secType,
                                        client=self)
     return asset_key
Example #7
0
    def get(self) -> Response:
        """Endpoint (private) provides the price of a specified asset on a given day.

        Returns:
            Response -- The flask Response object.
        """
        args = PRICING_PARSER.parse_args()
        asset = Asset.get_by_id(args['asset_id'])
        if asset is None:
            return abort(400, "Invalid {asset_id} given.")
        if args['date'] is None:
            return make_response(jsonify({"price": asset.get_price()}), 200)
        try:
            date = parser.parse(args['date'])
        except Exception:
            abort(400, "Invalid {date} given.")
        candle = asset.get_daily_candle(date.date())
        if candle is None:
            if date.date() == datetime.utcnow().date():
                return make_response(jsonify({"price": asset.get_price()}),
                                     200)
            return abort(
                400,
                "The specified {date} is outside the data available for the asset."
            )
        return make_response(jsonify({"price": candle.get_close()}), 200)
Example #8
0
 def get(self) -> Response:
     """Endpoint (private) for providing the Google Trends data associated with an Asset.
     
     Returns:
         Response -- The Flask response object.
     """
     args = TRENDS_READ_PARSER.parse_args()
     asset = Asset.get_by_id(args['asset_id'])
     if asset is None:
         return abort(400, "Invalid {asset_id} given.")
     if args['start_date'] is None:
         start_date = None
     else:
         try:
             start_date = parser.parse(args['start_date'])
         except Exception:
             abort(400, "Invalid {start_date} given.")
     if args['end_date'] is None:
         end_date = None
     else:
         try:
             end_date = parser.parse(args['end_date'])
         except Exception:
             abort(400, "Invalid {end_date} given.")
     trends = asset.get_trends(start=start_date, finish=end_date)
     trends_dict = [trend.as_dict() for trend in trends]
     return make_response(jsonify(trends_dict), 200)
def delete_asset(managed_portfolio: portfolio.Portfolio,
                 managed_asset: asset.Asset):
    """Deletes an asset from the portfolio.

  Args:
    managed_portfolio: Portfolio from which to delete asset.
    managed_asset: Asset to delete.

  Raises:
    ValueError: Asset does not exist in portfolio.

  Returns:
    Removed asset.
  """
    asset_id = managed_asset.get_id()
    if asset_id not in managed_portfolio.assets.keys():
        raise ValueError(
            f'{managed_asset} does not exist in {managed_portfolio}')

    # There is no need to remove operations as pickle will drop the asset and
    # all the operations linked to it.
    del managed_portfolio.assets[asset_id]
    portfolio_manager.store_portfolio(managed_portfolio)

    return managed_asset
Example #10
0
 def get(self) -> Response:
     """Endpoint (private) provides the historical candle data for a given asset.
     
     Returns:
         Response -- The flask Response object.
     """
     args = HISTORICAL_DAILY_PARSER.parse_args()
     asset = Asset.get_by_id(args['asset_id'])
     if asset is None:
         return abort(400, "Invalid {asset_id} given.")
     if args['start_date'] is None:
         start_date = None
     else:
         try:
             start_date = parser.parse(args['start_date'])
         except Exception:
             abort(400, "Invalid {start_date} given.")
     if args['end_date'] is None:
         end_date = None
     else:
         try:
             end_date = parser.parse(args['end_date'])
         except Exception:
             abort(400, "Invalid {end_date} given.")
     candles = asset.get_candles_within(start=start_date,
                                        finish=end_date,
                                        exclude_filler=True)
     candles_dict = [candle.as_dict() for candle in candles]
     return make_response(jsonify(candles_dict), 200)
Example #11
0
    def test_cancel_contract(self):
        # Create a user and asset
        user = User.create_user(self.session, 'user', 'abcd')
        usd = Asset.create_asset('USD')
        self.session.add_all([user, usd])
        self.session.commit()

        # Add funds to user1 so that we can create a contract
        user.increase_volume_of_asset(self.session, usd, Decimal('1'))

        # Let this user create a contract
        contract, asset = FuturesContract.create_contract(
            self.session, user,
            datetime.now() + timedelta(days=14), usd, Decimal('1'), 'FUTURE',
            Decimal('100'))
        assert contract is not None
        assert asset is not None

        # Now, money have been withdrawn from user1's account
        assert user.volume_of_asset(self.session, usd) == Decimal('0')

        # Cancel the contract
        assert contract.cancel(self.session) is True
        assert inspect(contract).deleted is True
        assert user.volume_of_asset(self.session, usd) == Decimal('1')

        # OK, the contract is cancelled.
        # Now do the same thing, but this time, create an order and verify that the cancelled flag is set instead
        contract, asset = FuturesContract.create_contract(
            self.session, user,
            datetime.now() + timedelta(days=14), usd, Decimal('1'), 'FUTURE',
            Decimal('100'))
        assert contract is not None
        assert asset is not None
        assert user.volume_of_asset(self.session, usd) == Decimal('0')

        ask_order = Order.create_order(self.session, user, Decimal('20'), usd,
                                       contract, Decimal('50'), False,
                                       OrderType.limit_order.value)
        assert ask_order is not None
        assert user.volume_of_asset(self.session, asset) == Decimal('50')

        # Assert that we cannot cancel the contract if there are created orders
        assert contract.cancel(self.session) is False

        # Put order into market
        assert put_order(self.session, ask_order) is None

        # Assert that we cannot cancel the contract if there are orders in the market
        assert contract.cancel(self.session) is False

        # It should be possible to cancel this order
        assert ask_order.cancel(self.session) is True
        assert user.volume_of_asset(self.session, asset) == Decimal('100')

        # Check that order is in the expected state
        assert contract.cancel(self.session) is True
        assert inspect(contract).deleted is False
        assert contract.cancelled is True
Example #12
0
 def get(self) -> Response:
     """Endpoint (public) provides a list of all the Assets and associated information.
     
     Returns:
         Response -- The flask Response object.
     """
     assets = Asset.get()
     assets_dict = [asset.as_dict() for asset in assets]
     return make_response(jsonify(assets_dict), 200)
Example #13
0
    def test_cancel_contract(self):
        # Create a user and asset
        user = User.create_user(self.session, "user", "abcd")
        usd = Asset.create_asset("USD")
        self.session.add_all([user, usd])
        self.session.commit()

        # Add funds to user1 so that we can create a contract
        user.increase_volume_of_asset(self.session, usd, Decimal("1"))

        # Let this user create a contract
        contract, asset = FuturesContract.create_contract(
            self.session, user, datetime.now() + timedelta(days=14), usd, Decimal("1"), "FUTURE", Decimal("100")
        )
        assert contract is not None
        assert asset is not None

        # Now, money have been withdrawn from user1's account
        assert user.volume_of_asset(self.session, usd) == Decimal("0")

        # Cancel the contract
        assert contract.cancel(self.session) is True
        assert inspect(contract).deleted is True
        assert user.volume_of_asset(self.session, usd) == Decimal("1")

        # OK, the contract is cancelled.
        # Now do the same thing, but this time, create an order and verify that the cancelled flag is set instead
        contract, asset = FuturesContract.create_contract(
            self.session, user, datetime.now() + timedelta(days=14), usd, Decimal("1"), "FUTURE", Decimal("100")
        )
        assert contract is not None
        assert asset is not None
        assert user.volume_of_asset(self.session, usd) == Decimal("0")

        ask_order = Order.create_order(
            self.session, user, Decimal("20"), usd, contract, Decimal("50"), False, OrderType.limit_order.value
        )
        assert ask_order is not None
        assert user.volume_of_asset(self.session, asset) == Decimal("50")

        # Assert that we cannot cancel the contract if there are created orders
        assert contract.cancel(self.session) is False

        # Put order into market
        assert put_order(self.session, ask_order) is None

        # Assert that we cannot cancel the contract if there are orders in the market
        assert contract.cancel(self.session) is False

        # It should be possible to cancel this order
        assert ask_order.cancel(self.session) is True
        assert user.volume_of_asset(self.session, asset) == Decimal("100")

        # Check that order is in the expected state
        assert contract.cancel(self.session) is True
        assert inspect(contract).deleted is False
        assert contract.cancelled is True
Example #14
0
 def get(self) -> Response:
     """Endpoint (public) provides the details of all assets containing the given asset_name.
     
     Returns:
         Response -- The flask Response object.
     """
     args = AUTOCOMPLETE_PARSER.parse_args()
     assets = Asset.autocomplete_by_name(args['asset_name'])
     assets_dict = [asset.as_dict_autocomplete() for asset in assets]
     return make_response(jsonify(assets_dict), 200)
Example #15
0
 def get(self) -> Response:
     """Endpoint (private) provides the performance of a specified asset over the current and previous day.
     
     Returns:
         Response -- The flask Response object.
     """
     args = PERFORMANCE_DAILY_PARSER.parse_args()
     asset = Asset.get_by_id(args['asset_id'])
     if asset is None:
         return abort(400, "Invalid {asset_id} given.")
     return make_response(jsonify(asset.get_daily_performance()), 200)
Example #16
0
 def get(self) -> Response:
     """Endpoint (private) provides the data associated with an Asset.
     
     Returns:
         Response -- The flask Response object.
     """
     args = READ_ASSET_PARSER.parse_args()
     asset = Asset.get_by_id(args['asset_id'])
     if asset is None:
         return abort(400, "Invalid {asset_id} given.")
     asset_dict = asset.as_dict()
     return make_response(jsonify(asset_dict), 200)
Example #17
0
    def create_contract(cls, session, user, expires_at, asset, asset_volume, contract_asset_name, contract_volume):
        if user.volume_of_asset(session, asset) < asset_volume:
            return None, None

        contract_asset = Asset.create_asset(contract_asset_name)
        contract = cls(created_at=datetime.now(), contract_type='Future', issuer=user, expires_at=expires_at,
                       volume=asset_volume, asset=asset, contract_asset=contract_asset)
        session.add_all([contract_asset, contract])
        user.increase_volume_of_asset(session, contract_asset, contract_volume)
        user.decrease_volume_of_asset(session, asset, asset_volume)

        logger.info('Created futures contract instance and asset with name "{}"'.format(contract_asset_name))

        return contract, contract_asset
Example #18
0
    def test_insufficient_funds(self):
        # Create a user and asset
        user = User.create_user(self.session, "user", "abcd")
        usd = Asset.create_asset("USD")
        self.session.add_all([user, usd])
        self.session.commit()

        # This user creates a contract without proper funding
        contract, asset = FuturesContract.create_contract(
            self.session, user, datetime.now() + timedelta(days=14), usd, Decimal("1"), "FUTURE", Decimal("100")
        )
        # Assert that this does not work
        assert contract is None
        assert asset is None
Example #19
0
    def test_insufficient_funds(self):
        # Create a user and asset
        user = User.create_user(self.session, 'user', 'abcd')
        usd = Asset.create_asset('USD')
        self.session.add_all([user, usd])
        self.session.commit()

        # This user creates a contract without proper funding
        contract, asset = FuturesContract.create_contract(
            self.session, user,
            datetime.now() + timedelta(days=14), usd, Decimal('1'), 'FUTURE',
            Decimal('100'))
        # Assert that this does not work
        assert contract is None
        assert asset is None
Example #20
0
    def create_contract(cls, session, user, expires_at, asset, asset_volume,
                        contract_asset_name, contract_volume):
        if user.volume_of_asset(session, asset) < asset_volume:
            return None, None

        contract_asset = Asset.create_asset(contract_asset_name)
        contract = cls(created_at=datetime.now(),
                       contract_type='Future',
                       issuer=user,
                       expires_at=expires_at,
                       volume=asset_volume,
                       asset=asset,
                       contract_asset=contract_asset)
        session.add_all([contract_asset, contract])
        user.increase_volume_of_asset(session, contract_asset, contract_volume)
        user.decrease_volume_of_asset(session, asset, asset_volume)

        logger.info(
            'Created futures contract instance and asset with name "{}"'.
            format(contract_asset_name))

        return contract, contract_asset
Example #21
0
 def patch(self) -> Response:
     """Endpoint (private) allows a User to update their profile details.
     
     Returns:
         Response -- The Flask response object.
     """
     args = UPDATE_PARSER.parse_args()
     user = User.get_by_email(get_jwt_identity())
     if user is None:
         return abort(401, "You are not permitted to access this endpoint.")
     if args['fullname'] is not None:
         if args['fullname'] == "":
             return abort(400, "Your {fullname} cannot be empty.")
         user.set_name(args['fullname'])
     if args['currency_id'] is not None:
         currency = Asset.get_by_id(args['currency_id'])
         if currency is None:
             return abort(400, "An invalid {currency_id} was given as a base currency.")
         if currency.get_asset_class() != "Currency":
             return abort(400, "The provided {currency_id} is not a currency.")
         user.set_base_currency(currency)
     user.save()
     return make_response(jsonify({"msg": "The user details have been successfully updated."}), 200)
Example #22
0
 def insert(self, dto):
     reg = Asset()
     reg.map(dto)
     reg.calculate()
     return AssetDb().insert(reg)
Example #23
0
 def post(self) -> Response:
     """Endpoint (private) responsible for allowing a User to create a Transaction.
     
     Returns:
         Response -- The Flask response object.
     """
     args = CREATE_PARSER.parse_args()
     user = User.get_by_email(get_jwt_identity())
     if user is None:
         return abort(403, "You are not permitted to create a transaction.")
     asset = Asset.get_by_id(args['asset_id'])
     if asset is None:
         return abort(400, "Invalid {asset_id} has been specified.")
     try:
         asset_quantity = float(args['quantity'])
     except Exception:
         return abort(400, "Invalid asset {quantity} specified.")
     if asset_quantity <= 0:
         return abort(400,
                      "The {quantity} cannot be less than or equal to 0.")
     try:
         date_purchased = parser.parse(args['date_purchased'])
         date_purchased = date_purchased.replace(tzinfo=None)
     except Exception:
         return abort(400, "Invalid {date_purchased} specified.")
     if date_purchased > datetime.utcnow():
         return abort(400, "The {date_purchased} cannot be ahead of time.")
     purchase_candle = asset.get_daily_candle(date_purchased)
     if purchase_candle is None and date_purchased.date(
     ) != datetime.utcnow().date():
         return abort(
             400,
             "The given {date_purchased} is prior to the platform's pricing history for the asset."
         )
     if args['price_purchased'] is None:
         if purchase_candle is None:
             price_purchased = asset.get_price()
         else:
             price_purchased = purchase_candle.get_close()
     else:
         try:
             price_purchased = float(args['price_purchased'])
         except Exception:
             return abort(400, "Invalid {price_purchased} given.")
         if price_purchased <= 0:
             return abort(
                 400,
                 "The {price_purchased} cannot be less than or equal to 0.")
     if args['date_sold'] is None or args['date_sold'] == "":
         date_sold = None
         price_sold = None
     else:
         try:
             date_sold = parser.parse(args['date_sold'])
             date_sold = date_sold.replace(tzinfo=None)
         except Exception:
             return abort(400, "Invalid {date_sold} specified.")
         if date_sold > datetime.utcnow():
             return abort(400, "The {date_sold} cannot be ahead of time.")
         if date_sold <= date_purchased:
             return abort(
                 400,
                 "The {date_sold} must be further in time than the {date_purchased}."
             )
         if args['price_sold'] is None:
             if date_sold.date() == datetime.utcnow().date():
                 price_sold = asset.get_price()
             else:
                 sell_candle = asset.get_daily_candle(date_sold)
                 if sell_candle is None:
                     return abort(
                         400,
                         "The given {date_sold} has no data for the asset in the platform's pricing history."
                     )
                 price_sold = sell_candle.get_close()
         else:
             if date_sold.date() != datetime.utcnow().date():
                 sell_candle = asset.get_daily_candle(date_sold)
                 if sell_candle is None:
                     return abort(
                         400,
                         "The given {date_sold} has no data for the asset in the platform's pricing history."
                     )
             try:
                 price_sold = float(args['price_sold'])
             except Exception:
                 return abort(400, "Invalid {price_sold} given.")
             if price_sold < 0:
                 return abort(400,
                              "The {price_sold} cannot be less than 0.")
     new_transaction = Transaction.create(user, asset, asset_quantity,
                                          date_purchased, date_sold,
                                          price_purchased, price_sold)
     if new_transaction is None:
         return abort(500, "An error occurred in creating the transaction.")
     return make_response(
         jsonify({"msg": "The transaction has been successfully created."}),
         200)
Example #24
0
 def patch(self) -> Response:
     """Endpoint (private) responsible for updating the details of a User's Transaction.
     
     Returns:
         Response -- The Flask response object.
     """
     args = UPDATE_PARSER.parse_args()
     transaction = Transaction.get_by_id(args['transaction_id'])
     if transaction is None:
         return abort(400, "Invalid {transaction_id} specified.")
     if transaction.get_user().get_email() != get_jwt_identity():
         return abort(401,
                      "You are not authorised to update this transaction.")
     if args['asset_id'] is not None:
         asset = Asset.get_by_id(args['asset_id'])
         if asset is None:
             return abort(400, "Invalid {asset_id} specified.")
         transaction.set_asset(asset)
     if args['quantity'] is not None:
         try:
             quantity = float(args['quantity'])
         except Exception:
             return abort(400, "Invalid {quantity} specified.")
         if quantity <= 0:
             return abort(
                 400, "The {quantity} cannot be less than or equal to 0.")
         transaction.set_quantity(quantity)
     if args['date_purchased'] is not None:
         try:
             date_purchased = parser.parse(args['date_purchased'])
             date_purchased = date_purchased.replace(tzinfo=None)
         except Exception:
             return abort(400, "Invalid {date_purchased} specified.")
         if date_purchased > datetime.utcnow():
             return abort(400,
                          "The {date_purchased} cannot be ahead of time.")
         purchase_candle = transaction.get_asset().get_daily_candle(
             date_purchased)
         if purchase_candle is None and (date_purchased.date() !=
                                         datetime.utcnow().date()):
             return abort(
                 400,
                 "The given {date_purchased} is prior to the platform's pricing history for the asset."
             )
         transaction.set_buy_date(date_purchased)
     if args['price_purchased'] is not None:
         try:
             price_purchased = float(args['price_purchased'])
         except Exception:
             return abort(400, "Invalid {price_purchased} specified.")
         if price_purchased <= 0:
             return abort(
                 400,
                 "The {price_purchased} cannot be less than or equal to 0.")
         transaction.set_buy_price(price_purchased)
     else:
         if args['date_purchased'] is not None:
             if purchase_candle is None:
                 transaction.set_buy_price(
                     transaction.get_asset().get_price())
             else:
                 transaction.set_buy_price(purchase_candle.get_close())
     if args['date_sold'] is not None:
         if args['date_sold'] == "":
             transaction.set_sell_date(None)
             transaction.set_sell_price(None)
         else:
             try:
                 date_sold = parser.parse(args['date_sold'])
                 date_sold = date_sold.replace(tzinfo=None)
             except Exception:
                 return abort(400, "Invalid {date_sold} specified.")
             if date_sold > datetime.utcnow():
                 return abort(400,
                              "The {date_sold} cannot be ahead of time.")
             if date_sold <= transaction.get_buy_date():
                 return abort(
                     400,
                     "The {date_sold} must be further ahead in time than the {date_purchased}."
                 )
             sell_candle = transaction.get_asset().get_daily_candle(
                 date_sold)
             if sell_candle is None and date_sold.date() != datetime.utcnow(
             ).date():
                 return abort(
                     400,
                     "The given {date_sold} is outside the platform's pricing history for the asset."
                 )
             transaction.set_sell_date(date_sold)
     if args['price_sold'] is not None:
         if transaction.get_sell_date() is None:
             return abort(
                 400,
                 "The {price_sold} field cannot be set while {date_sold} hasn't been set."
             )
         try:
             price_sold = float(args['price_sold'])
         except Exception:
             return abort(400, "Invalid {price_sold} specified.")
         if price_sold < 0:
             return abort(400, "The {price_sold} cannot be less than 0.")
         transaction.set_sell_price(price_sold)
     else:
         if transaction.get_sell_date() is not None:
             if date_sold.date() == datetime.utcnow().date():
                 transaction.set_sell_price(
                     transaction.get_asset().get_price())
             else:
                 sell_candle = transaction.get_asset().get_daily_candle(
                     date_sold)
                 if sell_candle is None:
                     return abort(
                         400,
                         "The given {date_sold} has no data for the asset in the platform's pricing history."
                     )
                 transaction.set_sell_price(sell_candle.get_close())
     transaction.save()
     user = transaction.user.fetch()
     user.set_portfolio_historical(None)
     user.save()
     return make_response(
         jsonify({"msg": "The transaction was successfully updated."}), 200)
Example #25
0
 def set_asset(self, guid, description, type, uri, duration_secs=None, pin=None, how_many=None, shuffle=None):
     self.kv.set_asset(guid, Asset(uri, guid, description, type, duration_secs, pin, how_many, shuffle))
Example #26
0
async def load_location(sid: str, location: Location, *, complete=False):
    pr: PlayerRoom = game_state.get(sid)
    if pr.active_location != location:
        pr.active_location = location
        pr.save()

    # 1. Load client options

    client_options = pr.player.as_dict()
    client_options["location_user_options"] = LocationUserOption.get(
        user=pr.player, location=location).as_dict()
    client_options["default_user_options"] = pr.player.default_options.as_dict(
    )

    if pr.user_options:
        client_options["room_user_options"] = pr.user_options.as_dict()

    await sio.emit("Client.Options.Set",
                   client_options,
                   room=sid,
                   namespace=GAME_NS)

    # 2. Load room info

    if complete:
        await sio.emit(
            "Room.Info.Set",
            {
                "name":
                pr.room.name,
                "creator":
                pr.room.creator.name,
                "invitationCode":
                str(pr.room.invitation_code),
                "isLocked":
                pr.room.is_locked,
                "default_options":
                pr.room.default_options.as_dict(),
                "players": [{
                    "id": rp.player.id,
                    "name": rp.player.name,
                    "location": rp.active_location.id,
                    "role": rp.role,
                } for rp in pr.room.players],
                "publicName":
                config.get("General", "public_name", fallback=""),
            },
            room=sid,
            namespace=GAME_NS,
        )

    # 3. Load location

    await sio.emit("Location.Set",
                   location.as_dict(),
                   room=sid,
                   namespace=GAME_NS)

    # 4. Load all location settings (DM)

    if complete and pr.role == Role.DM:
        await sio.emit(
            "Locations.Settings.Set",
            {
                l.id: {} if l.options is None else l.options.as_dict()
                for l in pr.room.locations
            },
            room=sid,
            namespace=GAME_NS,
        )

    # 5. Load Board

    locations = [{
        "id": l.id,
        "name": l.name,
        "archived": l.archived
    } for l in pr.room.locations.order_by(Location.index)]
    await sio.emit("Board.Locations.Set",
                   locations,
                   room=sid,
                   namespace=GAME_NS)

    floors = [floor for floor in location.floors.order_by(Floor.index)]

    if "active_floor" in client_options["location_user_options"]:
        index = next(i for i, f in enumerate(floors) if f.name ==
                     client_options["location_user_options"]["active_floor"])
        lower_floors = floors[index - 1::-1] if index > 0 else []
        higher_floors = floors[index + 1:] if index < len(floors) else []
        floors = [floors[index], *lower_floors, *higher_floors]

    for floor in floors:
        await sio.emit(
            "Board.Floor.Set",
            floor.as_dict(pr.player, pr.role == Role.DM),
            room=sid,
            namespace=GAME_NS,
        )

    # 6. Load Initiative

    location_data = Initiative.get_or_none(location=location)
    if location_data:
        await sio.emit("Initiative.Set",
                       location_data.as_dict(),
                       room=sid,
                       namespace=GAME_NS)

    # 7. Load labels

    if complete:
        labels = Label.select().where((Label.user == pr.player)
                                      | (Label.visible == True))
        label_filters = LabelSelection.select().where(
            (LabelSelection.user == pr.player)
            & (LabelSelection.room == pr.room))

        await sio.emit(
            "Labels.Set",
            [l.as_dict() for l in labels],
            room=sid,
            namespace=GAME_NS,
        )
        await sio.emit(
            "Labels.Filters.Set",
            [l.label.uuid for l in label_filters],
            room=sid,
            namespace=GAME_NS,
        )

    # 8. Load Notes

    await sio.emit(
        "Notes.Set",
        [
            note.as_dict()
            for note in Note.select().where((Note.user == pr.player)
                                            & (Note.room == pr.room))
        ],
        room=sid,
        namespace=GAME_NS,
    )

    # 9. Load Markers

    await sio.emit(
        "Markers.Set",
        [
            marker.as_string()
            for marker in Marker.select(Marker.shape_id).where(
                (Marker.user == pr.player) & (Marker.location == location))
        ],
        room=sid,
        namespace=GAME_NS,
    )

    # 10. Load Assets

    if complete:
        await sio.emit(
            "Asset.List.Set",
            Asset.get_user_structure(pr.player),
            room=sid,
            namespace=GAME_NS,
        )
Example #27
0
 def update(self, id, dto):
     reg = Asset()
     reg.map(dto)
     reg.calculate()
     return AssetDb().update(id, reg)