# -*- coding: utf-8 -*-
import click
import sys
import logging
import datetime
from cointrader import db, STRATEGIES
from cointrader.config import Config, get_path_to_config
from cointrader.exchange import Poloniex, BacktestMarket, Market
from cointrader.exchanges.poloniex import ApiError
from cointrader.bot import init_db, get_bot
from cointrader.helpers import render_bot_statistic, render_bot_tradelog
log = logging.getLogger(__name__)
[docs]class Context(object):
"""Docstring for Context. """
def __init__(self):
self.exchange = None
pass_context = click.make_pass_decorator(Context, ensure=True)
@click.group()
@click.option("--config", help="Configuration File for cointrader.", type=click.File("r"))
@pass_context
def main(ctx, config):
"""Console script for cointrader on the Poloniex exchange"""
init_db()
if config:
config = Config(config)
else:
config = Config(open(get_path_to_config(), "r"))
try:
ctx.exchange = Poloniex(config)
except ApiError as ex:
click.echo(ex.message)
sys.exit(1)
@click.command()
@click.option("--order-by-volume", help="Order markets by their trading volume", is_flag=True)
@click.option("--order-by-profit", help="Order markets by their current profit", is_flag=True)
@click.option("--limit", help="Limit output to NUM markets", default=10)
@pass_context
def explore(ctx, order_by_volume, order_by_profit, limit):
"""List top markets. On default list markets which are profitable and has a high volume."""
markets = ctx.exchange.markets
if not order_by_volume and not order_by_profit:
markets = ctx.exchange.get_top_markets(markets, limit)
for market in markets:
url = "https://poloniex.com/exchange#{}".format(market[0].lower())
click.echo("{:<10} {:>6}% {:>10} {:>20}".format(market[0], market[1]["change"], market[1]["volume"], url))
if len(markets) == 0:
click.echo("Sorry. Can not find any market which is in the TOP{} for profit and trade volume. Try to increase the limit using the --limit parameter.".format(limit))
elif order_by_volume:
markets = ctx.exchange.get_top_volume_markets(markets, limit)
for market in markets:
url = "https://poloniex.com/exchange#{}".format(market[0].lower())
click.echo("{:<10} {:>10} {:>6}% {:>20}".format(market[0], market[1]["volume"], market[1]["change"], url))
if len(markets) == 0:
click.echo("Sorry. Can not find any market which is in the TOP{} for trade volume. Try to increase the limit using the --limit parameter.".format(limit))
elif order_by_profit:
markets = ctx.exchange.get_top_profit_markets(markets, limit)
for market in markets:
url = "https://poloniex.com/exchange#{}".format(market[0].lower())
click.echo("{:<10} {:>6}% {:>10} {:>20}".format(market[0], market[1]["change"], market[1]["volume"], url))
if len(markets) == 0:
click.echo("Sorry. Can not find any market which is in the TOP{} for profit. Try to increase the limit using the --limit parameter.".format(limit))
@click.command()
@pass_context
def balance(ctx):
"""Overview of your balances on the market."""
click.echo("{:<4} {:>12} {:>12}".format("CUR", "total", "btc_value"))
click.echo("{}".format("-" * 31))
coins = ctx.exchange.coins
for currency in coins:
click.echo("{:<4}: {:>12} {:>12}".format(currency, coins[currency].quantity, coins[currency].value))
click.echo("{}".format("-" * 31))
click.echo("{:<9}: {:>20}".format("TOTAL BTC", ctx.exchange.total_btc_value))
click.echo("{:<9}: {:>20}".format("TOTAL USD", ctx.exchange.total_euro_value))
@click.command()
@click.argument("market")
@click.option("--resolution", help="Resolution of the chart which is used for trend analysis", default="30m")
@click.option("--start", help="Datetime to begin trading", default=None)
@click.option("--end", help="Datetime to end trading", default=None)
@click.option("--automatic", help="Start cointrader in automatic mode.", is_flag=True)
@click.option("--backtest", help="Just backtest the strategy on the chart.", is_flag=True)
@click.option("--papertrade", help="Just simulate the trading.", is_flag=True)
@click.option("--strategy", help="Stratgegy used for trading.", default="Wait", type=click.Choice(STRATEGIES.keys()))
@click.option("--btc", help="Set initial amount of BTC the bot will use for trading.", type=float)
@click.option("--coins", help="Set initial amount of coint the bot will use for trading.", type=float)
@pass_context
def start(ctx, market, resolution, start, end, automatic, backtest, papertrade, strategy, btc, coins):
"""Start a new bot on the given market and the given amount of BTC"""
# Check start and end date
try:
if start:
start = datetime.datetime.strptime(start, "%Y-%m-%d %H:%M:%S")
if end:
end = datetime.datetime.strptime(end, "%Y-%m-%d %H:%M:%S")
except ValueError:
click.echo("Date is not valid. Must be in format 'YYYY-mm-dd HH:MM:SS'")
sys.exit(1)
# Build the market on which the bot will operate
# First check if the given market is a valid market. If not exit
# here with a error message.
# If the market is valid create a real market instance of and
# instance for backtests depending on the user input.
if ctx.exchange.is_valid_market(market):
if backtest:
if start is None or end is None:
click.echo("Error! For backtests you must provide a timeframe by setting start and end!")
sys.exit(1)
market = BacktestMarket(ctx.exchange, market)
else:
market = Market(ctx.exchange, market)
else:
click.echo("Market {} is not available".format(market))
sys.exit(1)
# Check if the given resolution is supported
if not ctx.exchange.is_valid_resolution(resolution):
valid_resolutions = ", ".join(ctx.exchange.resolutions.keys())
click.echo("Resolution {} is not supported.\n"
"Please choose one of the following: {}".format(resolution,
valid_resolutions))
sys.exit(1)
# Initialise a strategy.
strategy = STRATEGIES[strategy]()
bot = get_bot(market, strategy, resolution, start, end, btc, coins)
bot.start(backtest, automatic)
if backtest:
click.echo(render_bot_tradelog(bot.trades))
click.echo(render_bot_statistic(bot.stat(backtest)))
db.delete(bot)
db.commit()
@click.command()
@click.argument("dollar", type=float)
@pass_context
def exchange(ctx, dollar):
"""Will return how many BTC you get for the given amount of dollar"""
btc = ctx.exchange.dollar2btc(dollar)
click.echo("{}$ ~ {}BTC".format(dollar, btc))
main.add_command(explore)
main.add_command(balance)
main.add_command(exchange)
main.add_command(start)