From c3c1cbec0973a2ec817c982a6a540ae2b7cfca31 Mon Sep 17 00:00:00 2001 From: andrew saintway Date: Wed, 27 Jan 2021 02:26:20 +0900 Subject: [PATCH] add the logic of including the handling fee --- ...{main-test.ipynb => main-martingale.ipynb} | 151 +---- main-constant-threshold.ipynb | 604 ++++++++++++++++++ main-xlm.ipynb | 2 +- main.ipynb | 2 +- 4 files changed, 624 insertions(+), 135 deletions(-) rename graph/{main-test.ipynb => main-martingale.ipynb} (82%) create mode 100644 main-constant-threshold.ipynb diff --git a/graph/main-test.ipynb b/graph/main-martingale.ipynb similarity index 82% rename from graph/main-test.ipynb rename to graph/main-martingale.ipynb index 1d0e75c..ce1eea1 100644 --- a/graph/main-test.ipynb +++ b/graph/main-martingale.ipynb @@ -116,13 +116,13 @@ " return self.total_gained_fiat_money + self.get_gain_fiat_money()\n", "\n", " def __str__(self):\n", - " sell_fiat_price_description = f'{self.now_sell_fiat_price}'\n", + " sell_fiat_price_description = f'{self.now_sell_fiat_price:.2f}'\n", " if self.bought_average_fiat_price is not None:\n", " diff_fiat_price = self.now_sell_fiat_price - self.bought_average_fiat_price\n", - " sell_fiat_price_description = f'{diff_fiat_price:.2f} = {self.now_sell_fiat_price} - {self.bought_average_fiat_price:.2f}'\n", + " sell_fiat_price_description = f'{diff_fiat_price:.2f} = {self.now_sell_fiat_price:.2f} - {self.bought_average_fiat_price:.2f}'\n", " return (\n", " f'GAIN {self.get_total_gain_fiat_money():+.2f} = {self.total_gained_fiat_money:+.2f} {self.get_gain_fiat_money():+.2f} JPY in total by {self.get_robot_title()}\\n'\n", - " f'SELL {self.bought_amount:.4f} ETH for {sell_fiat_price_description} JPY/ETH. BUY for {self.now_buy_fiat_price} JPY/ETH.\\n'\n", + " f'SELL {self.bought_amount:.4f} ETH for {sell_fiat_price_description} JPY/ETH. BUY for {self.now_buy_fiat_price:.2f} JPY/ETH.\\n'\n", " )\n", "\n", " def estimate_gained_fiat_money(self, sell_unit_amount, sell_fiat_price=None):\n", @@ -304,8 +304,8 @@ " def get_price(self):\n", " now_ticker = self.pub.get_ticker('eth_jpy')\n", " return {\n", - " 'now_sell_fiat_price': int(now_ticker.get('buy', '0')),\n", - " 'now_buy_fiat_price': int(now_ticker.get('sell', '1'))\n", + " 'now_sell_fiat_price': int(now_ticker.get('buy', '0')) * (1 - 0.0012),\n", + " 'now_buy_fiat_price': int(now_ticker.get('sell', '1')) * (1 + 0.0012)\n", " }\n", "\n", " def buy(self, unit_amount, fiat_price=None):\n", @@ -331,7 +331,7 @@ " new_percentage = new_status.get_usage() * 100\n", "\n", " self.last_transaction = (\n", - " f'BOUGHT {amount:.4f} = -{old_amount:.4f}({old_percentage:.2f}%) +{new_amount:.4f}({new_percentage:.2f}%) ETH for {fiat_price} JPY/ETH:'\n", + " f'BOUGHT {amount:.4f} = -{old_amount:.4f} ({old_percentage:.2f}%) +{new_amount:.4f} ({new_percentage:.2f}%) ETH for {fiat_price:.2f} JPY/ETH:'\n", " f' NO.{new_status.trade_count + 1}-{new_status.buy_count} at {datetime.now()}\\n'\n", " )\n", "\n", @@ -368,8 +368,8 @@ " new_percentage = new_status.get_usage() * 100\n", "\n", " self.last_transaction = (\n", - " f'SOLD {amount:.4f} = +{old_amount:.4f}({old_percentage:.2f}%) -{new_amount:.4f}({new_percentage:.2f}%) ETH'\n", - " f' for {diff_price:.2f} = {fiat_price} - {old_avg_price:.2f} JPY/ETH: NO.{new_status.trade_count + 1}-{new_status.sell_count}\\n'\n", + " f'SOLD {amount:.4f} = +{old_amount:.4f} ({old_percentage:.2f}%) -{new_amount:.4f} ({new_percentage:.2f}%) ETH'\n", + " f' for {diff_price:.2f} = {fiat_price:.2f} - {old_avg_price:.2f} JPY/ETH: NO.{new_status.trade_count + 1}-{new_status.sell_count}\\n'\n", " f'GAINED {gained_fiat_money:+.2f} JPY: GAINED {new_status.total_gained_fiat_money:+.2f} JPY in total at {datetime.now()}\\n'\n", " )\n", "\n", @@ -453,17 +453,17 @@ " from unittest.mock import Mock\n", " bookkeeper.prv = Mock()\n", " while True:\n", - " # bought_unit_amounts = [\n", - " # int(Decimal(asset.get('free_amount', '0')) / Decimal(repr(TRADE_UNIT))) for asset in prv.get_asset().get('assets', []) \\\n", - " # if asset.get('asset', '') == 'eth'\n", - " # ] if not isinstance(prv, Mock) else []\n", + "# bought_unit_amounts = [\n", + "# int(Decimal(asset.get('free_amount', '0')) / Decimal(repr(TRADE_UNIT))) for asset in prv.get_asset().get('assets', []) \\\n", + "# if asset.get('asset', '') == 'eth'\n", + "# ] if not isinstance(prv, Mock) else []\n", "\n", - " # if len(bought_unit_amounts) > 0:\n", - " # bought_unit_amount_before = status.bought_unit_amount\n", + "# if len(bought_unit_amounts) > 0:\n", + "# bought_unit_amount_before = status.bought_unit_amount\n", "\n", - " # if bought_unit_amount_before > 0:\n", - " # status.bought_unit_amount = bought_unit_amounts[0]\n", - " # used_jpy *= status.bought_unit_amount / bought_unit_amount_before\n", + "# if bought_unit_amount_before > 0:\n", + "# status.bought_unit_amount = bought_unit_amounts[0]\n", + "# used_jpy *= status.bought_unit_amount / bought_unit_amount_before\n", "\n", " status.update(bookkeeper.get_price())\n", "\n", @@ -514,7 +514,7 @@ "\n", " send_slack(\n", " f'{bookkeeper.last_transaction}'\n", - " f'BY {status.get_robot_title()}',\n", + " f'BY {new_status.get_robot_title()}',\n", " 'Power by https://jhub.name/', 'good' if status.total_gained_fiat_money > 0 else 'danger'\n", " )\n", "\n", @@ -593,121 +593,6 @@ " status.sample_number += 1\n", " time.sleep(SAMPLE_INTERVAL / TEST_RATIO)" ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Simulated One" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from unittest.mock import Mock\n", - "prv = Mock()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Actual One" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "prv = python_bitbankcc.private(\n", - " os.environ['BITBANK_API_KEY'],\n", - " os.environ['BITBANK_API_SECRET']\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Trading Operations" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def sell_all():\n", - " now_ticker = pub.get_ticker('eth_jpy')\n", - " now_sell_jpy = float(now_ticker.get('buy', '0'))\n", - " now_buy_jpy = float(now_ticker.get('sell', '1'))\n", - "\n", - " please_sell_amount = TRADE_UNIT * bought_unit_amount\n", - " prv.order(\n", - " pair='eth_jpy', price=str(now_sell_jpy), amount=str(please_sell_amount), side='sell', order_type='market'\n", - " )\n", - "\n", - " bought_amount = TRADE_UNIT * bought_unit_amount\n", - " total_gain_jpy = total_gained_jpy + now_sell_jpy * bought_amount - used_jpy\n", - " with open('sample-history.txt', 'a', 1) as fsh:\n", - " fsh.write(\n", - " f'BUY ETH for {now_buy_jpy} JPY: SELL ETH for {now_sell_jpy} JPY\\n'\n", - " f'GAIN {total_gain_jpy} JPY in total at {datetime.now()}\\n\\n'\n", - " )\n", - " print(\n", - " f'BUY ETH for {now_buy_jpy} JPY: SELL ETH for {now_sell_jpy} JPY\\n'\n", - " f'GAIN {total_gain_jpy} JPY in total at {datetime.now()}\\n\\n',\n", - " end=''\n", - " )\n", - "\n", - " used_jpy_after = used_jpy * (bought_unit_amount - please_sell_unit_amount) / bought_unit_amount\n", - "\n", - " avg_jpy = used_jpy / bought_amount\n", - " diff_jpy = now_sell_jpy - avg_jpy\n", - " gained_jpy = diff_jpy * please_sell_amount\n", - " with open('transaction-history.txt', 'a', 1) as fth:\n", - " fth.write(\n", - " f'SOLD {please_sell_amount:.4f}=+{bought_amount:.4f}({used_jpy/MAX_TRADED_JPY*100:.2f}%)'\n", - " f'-{bought_amount-please_sell_amount:.4f}(0.00%) ETH'\n", - " f' for {diff_jpy:.2f}={now_sell_jpy}-{avg_jpy:.2f} JPY:BUY ETH for {now_buy_jpy} JPY\\n'\n", - " f'GAINED {gained_jpy} JPY: GAINED {total_gained_jpy + gained_jpy} JPY in total at {datetime.now()}\\n\\n'\n", - " )\n", - " print(\n", - " f'SOLD {please_sell_amount:.4f}=+{bought_amount:.4f}({used_jpy/MAX_TRADED_JPY*100:.2f}%)'\n", - " f'-{bought_amount-please_sell_amount:.4f}(0.00%) ETH'\n", - " f' for {diff_jpy:.2f}={now_sell_jpy}-{avg_jpy:.2f} JPY:BUY ETH for {now_buy_jpy} JPY\\n'\n", - " f'GAINED {gained_jpy} JPY: GAINED {total_gained_jpy + gained_jpy} JPY in total at {datetime.now()}\\n\\n',\n", - " end=''\n", - " )\n", - "\n", - " return {\n", - " 'sample_number': sample_number,\n", - " 'buy_count': buy_count,\n", - " 'sell_count': sell_count,\n", - " 'bought_unit_amount': bought_unit_amount,\n", - " 'used_jpy': used_jpy,\n", - " 'please_buy_unit_amount': please_buy_unit_amount,\n", - " 'please_sell_unit_amount': please_sell_unit_amount,\n", - " 'cooling_time': cooling_time,\n", - " 'total_gained_jpy': total_gained_jpy\n", - " }" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "sell_all()" - ] } ], "metadata": { diff --git a/main-constant-threshold.ipynb b/main-constant-threshold.ipynb new file mode 100644 index 0000000..a9cf0f7 --- /dev/null +++ b/main-constant-threshold.ipynb @@ -0,0 +1,604 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "WEBHOOK_URL = os.environ['SLACK_WEBHOOK_URL']\n", + "GOOD_CHANNEL_ID = os.environ['SLACK_GOOD_CHANNEL_ID']\n", + "DANGER_CHANNEL_ID = os.environ['SLACK_DANGER_CHANNEL_ID']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def send_slack(message, text, color='good'):\n", + " if color == 'good':\n", + " channel_id = GOOD_CHANNEL_ID\n", + " message = f':grinning: {message}'\n", + " if color == 'danger':\n", + " channel_id = DANGER_CHANNEL_ID\n", + " message = f':slightly_frowning_face: {message}'\n", + "\n", + " import requests\n", + " requests.post(\n", + " WEBHOOK_URL,\n", + " json={\n", + " 'channel': channel_id,\n", + " 'username': 'Trading Notifications',\n", + " 'icon_url': 'https://ethereum.org/favicon-32x32.png',\n", + " 'text': message,\n", + " 'mrkdwn': True,\n", + " 'attachments': [{\n", + " 'title': '→ Trading Operations',\n", + " 'title_link': 'https://jhub.name/user/sheng_wei/lab',\n", + " 'text': text,\n", + " 'color': color,\n", + " }]\n", + " }\n", + " )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# A Trader Stabilize Fiat Value of Crypto Currency" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import math" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "TEST_RATIO = 1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "SAMPLE_INTERVAL = 60\n", + "HAPPY_COOLING_TIME = 60\n", + "SAD_COOLING_TIME = 60 * 6\n", + "\n", + "TRADE_RATE = 10 << 10\n", + "NOTIFY_RATE = 60\n", + "BACKUP_RATE = 10\n", + "\n", + "TRADE_UNIT = 0.1\n", + "UNIT_CC_AVERAGE_JPY = 40000\n", + "MAX_TRADED_JPY = 800000\n", + "TRADABLE_UNIT_AMOUNT = MAX_TRADED_JPY / UNIT_CC_AVERAGE_JPY / TRADE_UNIT\n", + "\n", + "MIN_UNIT_CC_INIT_TRADE_JPY = 26500\n", + "MAX_UNIT_CC_INIT_TRADE_JPY = MIN_UNIT_CC_INIT_TRADE_JPY << 10\n", + "MAX_UNIT_CC_LOSS_JPY = MAX_UNIT_CC_INIT_TRADE_JPY\n", + "\n", + "MAX_GAIN_JPY = MAX_TRADED_JPY << 10 # useless\n", + "MAX_LOSS_JPY = MAX_TRADED_JPY << 10 # useless\n", + "MAX_TOTAL_LOST_JPY = MAX_TRADED_JPY << 10" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "TRADE_RATIO = 0.5" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "TRADABLE_UNIT_CC_GAIN_JPY = 1000 # TODO: self-adaptive by trend analysis\n", + "MIN_UNIT_CC_GAIN_JPY = TRADABLE_UNIT_CC_GAIN_JPY / math.log(TRADABLE_UNIT_AMOUNT, 1 + TRADE_RATIO) / TRADE_RATIO * (1 + TRADE_RATIO)\n", + "MIN_UNIT_CC_GAIN_JPY" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "TRADABLE_UNIT_CC_GAIN_JPY / math.log(TRADABLE_UNIT_AMOUNT)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "TRADABLE_UNIT_CC_LOSS_JPY = 3000 # TODO: self-adaptive by trend analysis\n", + "MIN_UNIT_CC_LOSS_JPY = TRADABLE_UNIT_CC_LOSS_JPY / math.log(TRADABLE_UNIT_AMOUNT, 1 + TRADE_RATIO) / TRADE_RATIO * (1 + TRADE_RATIO)\n", + "MIN_UNIT_CC_LOSS_JPY" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "TRADABLE_UNIT_CC_LOSS_JPY / math.log(TRADABLE_UNIT_AMOUNT)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from datetime import datetime\n", + "import json, sys, time\n", + "import python_bitbankcc" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pub = python_bitbankcc.public()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Simulated One" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from unittest.mock import Mock\n", + "prv = Mock()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Actual One" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# import os\n", + "# prv = python_bitbankcc.private(\n", + "# os.environ['BITBANK_API_KEY'],\n", + "# os.environ['BITBANK_API_SECRET']\n", + "# )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Trading Operations" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def sell_all():\n", + " now_ticker = pub.get_ticker('eth_jpy')\n", + " now_sell_jpy = int(now_ticker.get('buy', '0'))\n", + " now_buy_jpy = int(now_ticker.get('sell', '1'))\n", + "\n", + " please_sell_amount = TRADE_UNIT * bought_unit_amount\n", + " prv.order(\n", + " pair='eth_jpy', price=str(now_sell_jpy), amount=str(please_sell_amount), side='sell', order_type='market'\n", + " )\n", + "\n", + " bought_amount = TRADE_UNIT * bought_unit_amount\n", + " total_gain_jpy = total_gained_jpy + now_sell_jpy * bought_amount - used_jpy\n", + " with open('sample-history.txt', 'a', 1) as fsh:\n", + " fsh.write(\n", + " f'BUY ETH for {now_buy_jpy} JPY: SELL ETH for {now_sell_jpy} JPY\\n'\n", + " f'GAIN {total_gain_jpy} JPY in total at {datetime.now()}\\n\\n'\n", + " )\n", + " print(\n", + " f'BUY ETH for {now_buy_jpy} JPY: SELL ETH for {now_sell_jpy} JPY\\n'\n", + " f'GAIN {total_gain_jpy} JPY in total at {datetime.now()}\\n\\n',\n", + " end=''\n", + " )\n", + "\n", + " used_jpy_after = used_jpy * (bought_unit_amount - please_sell_unit_amount) / bought_unit_amount\n", + "\n", + " avg_jpy = used_jpy / bought_amount\n", + " diff_jpy = now_sell_jpy - avg_jpy\n", + " gained_jpy = diff_jpy * please_sell_amount\n", + " with open('transaction-history.txt', 'a', 1) as fth:\n", + " fth.write(\n", + " f'SOLD {please_sell_amount:.4f}=+{bought_amount:.4f}({used_jpy/MAX_TRADED_JPY*100:.2f}%)'\n", + " f'-{bought_amount-please_sell_amount:.4f}(0.00%) ETH'\n", + " f' for {diff_jpy:.2f}={now_sell_jpy}-{avg_jpy:.2f} JPY:BUY ETH for {now_buy_jpy} JPY\\n'\n", + " f'GAINED {gained_jpy} JPY: GAINED {total_gained_jpy + gained_jpy} JPY in total at {datetime.now()}\\n\\n'\n", + " )\n", + " print(\n", + " f'SOLD {please_sell_amount:.4f}=+{bought_amount:.4f}({used_jpy/MAX_TRADED_JPY*100:.2f}%)'\n", + " f'-{bought_amount-please_sell_amount:.4f}(0.00%) ETH'\n", + " f' for {diff_jpy:.2f}={now_sell_jpy}-{avg_jpy:.2f} JPY:BUY ETH for {now_buy_jpy} JPY\\n'\n", + " f'GAINED {gained_jpy} JPY: GAINED {total_gained_jpy + gained_jpy} JPY in total at {datetime.now()}\\n\\n',\n", + " end=''\n", + " )\n", + "\n", + " return {\n", + " 'sample_number': sample_number,\n", + " 'buy_count': buy_count,\n", + " 'sell_count': sell_count,\n", + " 'bought_unit_amount': bought_unit_amount,\n", + " 'used_jpy': used_jpy,\n", + " 'please_buy_unit_amount': please_buy_unit_amount,\n", + " 'please_sell_unit_amount': please_sell_unit_amount,\n", + " 'cooling_time': cooling_time,\n", + " 'total_gained_jpy': total_gained_jpy\n", + " }" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Start Trading" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ROBOT_NAME = 'Short-Term Robot'\n", + "send_slack(\n", + " f'{\"Mock of \" if isinstance(prv, Mock) else \"\"}{ROBOT_NAME} started', 'Power by https://jhub.name/', 'good'\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import yaml\n", + "\n", + "ROBOT_ID = 'robot-status'\n", + "\n", + "PATH = os.getenv('ROBOT_PATH') or '.'\n", + "STATUS_FILE = f'{PATH}/{ROBOT_ID}.yaml'\n", + "TMPFILE = f'{PATH}/_tmp'\n", + "\n", + "\n", + "def read_status():\n", + " if os.path.exists(STATUS_FILE):\n", + " with open(STATUS_FILE, 'r') as f:\n", + " return yaml.load(f, Loader=yaml.FullLoader)\n", + " else:\n", + " return {}\n", + "\n", + "\n", + "def write_status(status):\n", + " with open(TMPFILE, 'w') as f:\n", + " yaml.dump(status, f)\n", + " os.replace(TMPFILE, STATUS_FILE)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "status = read_status()\n", + "sample_number = status.get('sample_number', 0)\n", + "trade_count = status.get('trade_count', 0)\n", + "buy_count = status.get('buy_count', 0)\n", + "sell_count = status.get('sell_count', 0)\n", + "bought_unit_amount = status.get('bought_unit_amount', 0)\n", + "used_jpy = status.get('used_jpy', 0)\n", + "bought_average_jpy = status.get('bought_average_jpy', MAX_UNIT_CC_INIT_TRADE_JPY)\n", + "sold_unit_amount = status.get('sold_unit_amount', 0)\n", + "got_jpy = status.get('got_jpy', 0)\n", + "sold_average_jpy = status.get('sold_average_jpy', MAX_UNIT_CC_INIT_TRADE_JPY)\n", + "please_buy_unit_amount = status.get('please_buy_unit_amount', 0)\n", + "please_sell_unit_amount = status.get('please_sell_unit_amount', 0)\n", + "cooling_time = status.get('cooling_time', HAPPY_COOLING_TIME)\n", + "total_gained_jpy = status.get('total_gained_jpy', 0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "with open('sample-history.txt', 'a', 1) as fsh, open('transaction-history.txt', 'a', 1) as fth:\n", + " while True:\n", + " now_ticker = pub.get_ticker('eth_jpy')\n", + " now_sell_jpy = int(now_ticker.get('buy', '0'))\n", + " now_buy_jpy = int(now_ticker.get('sell', '1'))\n", + "\n", + " bought_amount = TRADE_UNIT * bought_unit_amount\n", + "\n", + " if sample_number % TRADE_RATE == 0 and bought_unit_amount > 0 and now_sell_jpy > used_jpy/bought_amount:\n", + " please_sell_unit_amount = 1\n", + " cooling_time = HAPPY_COOLING_TIME\n", + "\n", + " if sold_unit_amount == 0 and bought_unit_amount > 0 and now_sell_jpy > used_jpy/bought_amount:\n", + " sample_number = 0\n", + " please_sell_unit_amount = 1\n", + " cooling_time = HAPPY_COOLING_TIME\n", + "\n", + " if sold_unit_amount > 0 and now_sell_jpy > got_jpy / (TRADE_UNIT * sold_unit_amount) + MIN_UNIT_CC_GAIN_JPY:\n", + " trade_unit_amount = min(math.ceil(sold_unit_amount * TRADE_RATIO), bought_unit_amount)\n", + " if trade_unit_amount > 0:\n", + " sample_number = 0\n", + " please_sell_unit_amount = trade_unit_amount\n", + " cooling_time = HAPPY_COOLING_TIME\n", + "\n", + " if now_sell_jpy * bought_amount - used_jpy > MAX_GAIN_JPY:\n", + " sample_number = 0\n", + " please_sell_unit_amount = bought_unit_amount\n", + " cooling_time = HAPPY_COOLING_TIME\n", + "\n", + " if now_sell_jpy * bought_amount - used_jpy < -MAX_LOSS_JPY:\n", + " sample_number = 0\n", + " please_sell_unit_amount = bought_unit_amount\n", + " cooling_time = SAD_COOLING_TIME\n", + "\n", + " if bought_unit_amount > 0 and now_sell_jpy < used_jpy/bought_amount - MAX_UNIT_CC_LOSS_JPY and used_jpy/MAX_TRADED_JPY > 90/100:\n", + " please_sell_unit_amount = bought_unit_amount\n", + " cooling_time = SAD_COOLING_TIME\n", + "\n", + " if bought_unit_amount > 0 and now_sell_jpy < MIN_UNIT_CC_INIT_TRADE_JPY:\n", + " please_sell_unit_amount = bought_unit_amount\n", + " cooling_time = SAD_COOLING_TIME\n", + "\n", + " if please_sell_unit_amount > 0:\n", + " please_sell_amount = TRADE_UNIT * please_sell_unit_amount\n", + " prv.order(\n", + " pair='eth_jpy', price=str(now_sell_jpy), amount=str(please_sell_amount), side='sell', order_type='market'\n", + " )\n", + "\n", + " bought_amount = TRADE_UNIT * bought_unit_amount\n", + " gain_jpy = now_sell_jpy * bought_amount - used_jpy\n", + " total_gain_jpy = total_gained_jpy + gain_jpy\n", + " fsh.write(\n", + " f'BUY ETH for {now_buy_jpy} JPY: SELL ETH for {now_sell_jpy} JPY\\n'\n", + " f'GAIN {total_gain_jpy:+.2f}={total_gained_jpy:+.2f}{gain_jpy:+.2f} JPY in total at {datetime.now()}\\n\\n'\n", + " )\n", + "\n", + " used_jpy_after = used_jpy * (bought_unit_amount - please_sell_unit_amount) / bought_unit_amount\n", + "\n", + " avg_jpy = used_jpy / bought_amount\n", + " diff_jpy = now_sell_jpy - avg_jpy\n", + " gained_jpy = diff_jpy * please_sell_amount\n", + " total_gained_jpy += gained_jpy\n", + " fth.write(\n", + " f'SOLD {please_sell_amount:.4f}=+{bought_amount:.4f}({used_jpy/MAX_TRADED_JPY*100:.2f}%)'\n", + " f'-{bought_amount-please_sell_amount:.4f}({used_jpy_after/MAX_TRADED_JPY*100:.2f}%) ETH for {diff_jpy:.2f}'\n", + " f'={now_sell_jpy}-{avg_jpy:.2f} JPY:BUY ETH for {now_buy_jpy} JPY: NO.{trade_count+1}-{sell_count+1}\\n'\n", + " f'GAINED {gained_jpy:+.2f} JPY: GAINED {total_gained_jpy:+.2f} JPY in total at {datetime.now()}\\n\\n'\n", + " )\n", + "\n", + " send_slack(\n", + " f'Gained {gained_jpy:+.2f} JPY. Gained {total_gained_jpy:+.2f} JPY in total'\n", + " f' by {\"Mock of \" if isinstance(prv, Mock) else \"\"}{ROBOT_NAME}.',\n", + " 'Power by https://jhub.name/', 'good' if total_gained_jpy > 0 else 'danger'\n", + " )\n", + "\n", + " sell_count += 1\n", + " bought_unit_amount -= please_sell_unit_amount\n", + " used_jpy *= bought_unit_amount / (bought_unit_amount + please_sell_unit_amount)\n", + " sold_unit_amount += please_sell_unit_amount\n", + " got_jpy += now_sell_jpy * please_sell_amount\n", + " sold_average_jpy = got_jpy / (TRADE_UNIT * sold_unit_amount)\n", + " please_buy_unit_amount = 0\n", + " please_sell_unit_amount = 0\n", + " cooling_time = HAPPY_COOLING_TIME\n", + "\n", + " if bought_unit_amount == 0:\n", + " trade_count += 1\n", + " buy_count = sell_count = 0\n", + "\n", + " if bought_unit_amount == 0 and total_gained_jpy > MAX_GAIN_JPY << 2 and not isinstance(prv, Mock):\n", + " from unittest.mock import Mock\n", + " prv = Mock()\n", + " send_slack(\n", + " f'{ROBOT_NAME} is turned to Mock', 'Power by https://jhub.name/', 'good'\n", + " )\n", + "\n", + " write_status({\n", + " 'sample_number': sample_number + 1,\n", + " 'trade_count': trade_count,\n", + " 'buy_count': buy_count,\n", + " 'sell_count': sell_count,\n", + " 'bought_unit_amount': bought_unit_amount,\n", + " 'used_jpy': used_jpy,\n", + " 'bought_average_jpy': bought_average_jpy,\n", + " 'sold_unit_amount': sold_unit_amount,\n", + " 'got_jpy': got_jpy,\n", + " 'sold_average_jpy': sold_average_jpy,\n", + " 'please_buy_unit_amount': please_buy_unit_amount,\n", + " 'please_sell_unit_amount': please_sell_unit_amount,\n", + " 'cooling_time': cooling_time,\n", + " 'total_gained_jpy': total_gained_jpy,\n", + " 'trade_unit': TRADE_UNIT\n", + " })\n", + "\n", + " if total_gained_jpy < -MAX_TOTAL_LOST_JPY:\n", + " break\n", + "\n", + " sample_number += 1\n", + " time.sleep(cooling_time/TEST_RATIO)\n", + " continue\n", + "\n", + " if bought_unit_amount == 0 and now_buy_jpy > MIN_UNIT_CC_INIT_TRADE_JPY and now_buy_jpy < MAX_UNIT_CC_INIT_TRADE_JPY \\\n", + " and used_jpy + now_buy_jpy * TRADE_UNIT <= MAX_TRADED_JPY:\n", + " sample_number = 0\n", + " please_buy_unit_amount = 1\n", + "\n", + " if bought_unit_amount > 0 and now_buy_jpy < used_jpy/bought_amount - MIN_UNIT_CC_LOSS_JPY:\n", + " buy_unit_amount = math.ceil(bought_unit_amount * TRADE_RATIO)\n", + " while buy_unit_amount > 0 and used_jpy + now_buy_jpy * TRADE_UNIT * buy_unit_amount > MAX_TRADED_JPY:\n", + " buy_unit_amount >>= 1\n", + " if buy_unit_amount > 0:\n", + " sample_number = 0\n", + " please_buy_unit_amount = buy_unit_amount\n", + "\n", + " if please_buy_unit_amount > 0:\n", + " please_buy_amount = TRADE_UNIT * please_buy_unit_amount\n", + " prv.order(\n", + " pair='eth_jpy', price=str(now_buy_jpy), amount=str(please_buy_amount), side='buy', order_type='market'\n", + " )\n", + "\n", + " used_jpy_before = used_jpy\n", + "\n", + " buy_count += 1\n", + " bought_unit_amount += please_buy_unit_amount\n", + " used_jpy += now_buy_jpy * please_buy_amount\n", + " bought_average_jpy = used_jpy / (TRADE_UNIT * bought_unit_amount)\n", + " sold_unit_amount = 0\n", + " got_jpy = 0\n", + " please_buy_unit_amount = 0\n", + "\n", + " bought_amount = TRADE_UNIT * bought_unit_amount\n", + " avg_jpy = used_jpy / bought_amount\n", + " diff_jpy = now_sell_jpy - avg_jpy\n", + " gain_jpy = now_sell_jpy * bought_amount - used_jpy\n", + " total_gain_jpy = total_gained_jpy + gain_jpy\n", + " fth.write(\n", + " f'BOUGHT {please_buy_amount:.4f}=-{bought_amount-please_buy_amount:.4f}({used_jpy_before/MAX_TRADED_JPY*100:.2f}%)'\n", + " f'+{bought_amount:.4f}({used_jpy/MAX_TRADED_JPY*100:.2f}%) ETH for {now_buy_jpy} JPY: SELL {bought_amount:.4f} ETH'\n", + " f' for {diff_jpy:.2f}={now_sell_jpy}-{avg_jpy:.2f} JPY: NO.{trade_count+1}-{buy_count} at {datetime.now()}\\n'\n", + " f'GAIN {total_gain_jpy:+.2f}={total_gained_jpy:+.2f}{gain_jpy:+.2f} JPY in total at {datetime.now()}\\n\\n'\n", + " )\n", + " elif sample_number % TRADE_RATE == 0:\n", + " bought_amount = TRADE_UNIT * bought_unit_amount\n", + " sell_for_str = f'{now_sell_jpy}'\n", + " if bought_unit_amount > 0:\n", + " avg_jpy = used_jpy / bought_amount\n", + " diff_jpy = now_sell_jpy - avg_jpy\n", + " sell_for_str = f'{diff_jpy:.2f}={now_sell_jpy}-{avg_jpy:.2f}'\n", + " gain_jpy = now_sell_jpy * bought_amount - used_jpy\n", + " total_gain_jpy = total_gained_jpy + gain_jpy\n", + " fth.write(\n", + " f'BUY for {now_buy_jpy} JPY: SELL for {sell_for_str} JPY: at {datetime.now()}\\n'\n", + " f'GAIN {total_gain_jpy:+.2f}={total_gained_jpy:+.2f}{gain_jpy:+.2f} JPY in total at {datetime.now()}\\n\\n'\n", + " )\n", + "\n", + " bought_amount = TRADE_UNIT * bought_unit_amount\n", + " gain_jpy = now_sell_jpy * bought_amount - used_jpy\n", + " total_gain_jpy = total_gained_jpy + gain_jpy\n", + " fsh.write(\n", + " f'BUY ETH for {now_buy_jpy} JPY: SELL ETH for {now_sell_jpy} JPY\\n'\n", + " f'GAIN {total_gain_jpy:+.2f}={total_gained_jpy:+.2f}{gain_jpy:+.2f} JPY in total at {datetime.now()}\\n\\n'\n", + " )\n", + "\n", + " if sample_number % NOTIFY_RATE == 0:\n", + " bought_amount = TRADE_UNIT * bought_unit_amount\n", + " gain_jpy = now_sell_jpy * bought_amount - used_jpy\n", + " total_gain_jpy = total_gained_jpy + gain_jpy\n", + " avg_jpy_str = f'{used_jpy/bought_amount:.2f} / ' if bought_unit_amount > 0 else ''\n", + " mock_of_str = 'Mock of ' if isinstance(prv, Mock) else ''\n", + " send_slack(\n", + " f'Gain {total_gain_jpy:+.2f}={total_gained_jpy:+.2f}{gain_jpy:+.2f} JPY in total by {mock_of_str}{ROBOT_NAME}'\n", + " f' ({avg_jpy_str}{used_jpy/MAX_TRADED_JPY*100:.2f}%) at {datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")}\\n'\n", + " f'Buy ETH for {now_buy_jpy} JPY. Support level is {MIN_UNIT_CC_INIT_TRADE_JPY} JPY.',\n", + " 'Power by https://jhub.name/', 'good' if total_gain_jpy > 0 else 'danger'\n", + " )\n", + "\n", + " if sample_number % BACKUP_RATE == 0:\n", + " write_status({\n", + " 'sample_number': sample_number + 1,\n", + " 'trade_count': trade_count,\n", + " 'buy_count': buy_count,\n", + " 'sell_count': sell_count,\n", + " 'bought_unit_amount': bought_unit_amount,\n", + " 'used_jpy': used_jpy,\n", + " 'bought_average_jpy': bought_average_jpy,\n", + " 'sold_unit_amount': sold_unit_amount,\n", + " 'got_jpy': got_jpy,\n", + " 'sold_average_jpy': sold_average_jpy,\n", + " 'please_buy_unit_amount': please_buy_unit_amount,\n", + " 'please_sell_unit_amount': please_sell_unit_amount,\n", + " 'cooling_time': cooling_time,\n", + " 'total_gained_jpy': total_gained_jpy,\n", + " 'trade_unit': TRADE_UNIT\n", + " })\n", + "\n", + " sample_number += 1\n", + " time.sleep(SAMPLE_INTERVAL / TEST_RATIO)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sell_all()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.0" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/main-xlm.ipynb b/main-xlm.ipynb index 9182efe..d3eaae8 100644 --- a/main-xlm.ipynb +++ b/main-xlm.ipynb @@ -571,7 +571,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.7" + "version": "3.9.0" } }, "nbformat": 4, diff --git a/main.ipynb b/main.ipynb index 5506b9a..fd3f7de 100644 --- a/main.ipynb +++ b/main.ipynb @@ -587,7 +587,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.7" + "version": "3.9.0" } }, "nbformat": 4,