Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Size resolution is too high error, can't buy fractional? #62

Closed
gaborvecsei opened this issue Oct 29, 2021 · 2 comments
Closed

Size resolution is too high error, can't buy fractional? #62

gaborvecsei opened this issue Oct 29, 2021 · 2 comments

Comments

@gaborvecsei
Copy link

Description

Some problem with the order size. Seems like we can't buy fractional coins?

Of course it can easily happen that I misunderstood something, but then a more verbose error would be better

settings.json

{
  "settings": {
    "account_update_time": 5000,
    "use_sandbox": false,
    "use_sandbox_websockets": false,
    "websocket_buffer_size": 10000,
    "test_connectivity_on_auth": true,
    "coinbase_pro": {
      "cash": "EUR"
    }
  }
}

backtest.json (if applicable)

{
  "price_data": {
    "assets": []
  },
  "settings": {
    "use_price": "close",
    "smooth_prices": false,
    "GUI_output": false,
    "show_tickers_with_zero_delta": false,
    "save_initial_account_value": true,
    "show_progress_during_backtest": true,
    "cache_location": "./price_caches",
    "continuous_caching": true,
    "resample_account_value_for_metrics": "1d",
    "quote_account_value_in": "EUR",
    "ignore_user_exceptions": false
  }
}

Error (if applicable)

blankly.utils.exceptions.InvalidOrder: Size resolution is too high, the highest resolution allowed for this symbol is: 1e-08. You specified 0.008585614459548448.

Traceback (most recent call last):
  File "bot.py", line 36, in <module>
    results = strategy.backtest(to="1y", initial_values={"EUR": 100})
  File "/Users/gabor.vecsei/anaconda3/lib/python3.8/site-packages/blankly/frameworks/strategy/strategy_base.py", line 493, in backtest
    results = self.backtesting_controller.run()
  File "/Users/gabor.vecsei/anaconda3/lib/python3.8/site-packages/blankly/exchanges/interfaces/paper_trade/backtest_controller.py", line 878, in run
    metrics_indicators['Compound Annual Growth Rate (%)'] = metrics.cagr(dataframes)
  File "/Users/gabor.vecsei/anaconda3/lib/python3.8/site-packages/blankly/exchanges/interfaces/paper_trade/metrics.py", line 26, in cagr
    return round(metrics.cagr(account_values['value'].iloc[0], account_values['value'].iloc[-1], years), 2) * 100
  File "/Users/gabor.vecsei/anaconda3/lib/python3.8/site-packages/blankly/metrics/portfolio.py", line 31, in cagr
    return (end_value / start_value) ** (1 / years) - 1
ZeroDivisionError: division by zero

Platform Info

  • Python version: 3.8.5
  • Platform: MacOS

This was the quick test code which produced the error:

import blankly


def price_event(price, symbol, state: blankly.StrategyState):
    state.variables["step_count"] += 1

    if state.variables["step_count"] == 1:
        buy = state.interface.cash / price
        state.interface.market_order(symbol, side="buy", size=buy)

    if state.variables["step_count"] == 30:
        curr_value = state.interface.account[symbol].available
        state.interface.market_order(symbol, side='sell', size=curr_value)


def init(symbol, state: blankly.StrategyState):
    # Download price data to give context to the algo
    state.variables["history"] = state.interface.history(symbol, to=150, return_as="deque")["close"]
    state.variables["owns_position"] = False
    state.variables["step_count"] = 0


if __name__ == "__main__":
    # Authenticate coinbase pro strategy
    exchange = blankly.CoinbasePro(portfolio_name="algotrade_test_portfolio")

    # Use our strategy helper on coinbase pro
    strategy = blankly.Strategy(exchange)

    # Run the price event function every time we check for a new price - by default that is 15 seconds
    strategy.add_price_event(price_event, symbol="BTC-EUR", resolution="1d", init=init)

    # Start the strategy. This will begin each of the price event ticks
    # strategy.start()
    # Or backtest using this
    results = strategy.backtest(to="1y", initial_values={"EUR": 100})
    print(results)
@EmersonDove
Copy link
Member

EmersonDove commented Oct 29, 2021

Thanks for opening an issue!

In this case this should be expected behavior. Notice that when placing an order on Coinbase in the web interface, there is only a certain number of decimals you can put in your order size. In this case Coinbase enforces a maximum resolution of 1e-8 of your base currency.

You created an order for 0.008585614459548448 base, which has a higher resolution than coinbase allows. We enforce the resolutions in the backtest so that you can be confident your live model will also be able to accurately submit orders.

Solution:

This is why we built blankly.trunc().

Try wrapping your market orders to look like this:

state.interface.market_order(symbol, side="buy", size=blankly.trunc(buy, 8))
state.interface.market_order(symbol, side='sell', size=blankly.trunc(curr_value, 8))

This will enforce an 8 decimal accuracy and truncate higher accuracy decimals.

I recommend viewing the order filter we're checking with by doing:

print(state.interface.get_order_filter(symbol))

I will add a recommendation to use blankly.trunc to the error!

@gaborvecsei
Copy link
Author

@EmersonDove Thank you for the explanation and for extending the documentation!

EmersonDove added a commit that referenced this issue Nov 12, 2021
EmersonDove added a commit that referenced this issue Nov 20, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants