Skip to content

Commit

Permalink
detect portfolio changes and estimate robot status automatically
Browse files Browse the repository at this point in the history
  • Loading branch information
seii-saintway committed Jan 27, 2021
1 parent 5c4e48f commit dd42747
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 73 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ graph.md
*graph*.png
.ipynb_checkpoints/
__pycache__/
*.DS_Store
241 changes: 168 additions & 73 deletions graph/main-martingale.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -275,23 +275,34 @@
"source": [
"import copy\n",
"from datetime import datetime\n",
"from decimal import Decimal\n",
"import os\n",
"\n",
"import python_bitbankcc\n",
"\n",
"\n",
"class Portfolio(object):\n",
" def __init__(self, portfolio):\n",
" if isinstance(portfolio, type(self)):\n",
" self.__dict__.update(portfolio.__dict__)\n",
" if isinstance(portfolio, dict):\n",
" self.__dict__.update(portfolio)\n",
" if isinstance(portfolio, list):\n",
" self.__dict__.update(dict(portfolio))\n",
"\n",
"\n",
"class BookKeeper(object):\n",
" def __init__(self, status):\n",
" self.status = status\n",
" self.last_transaction = None\n",
"\n",
" self.pub = python_bitbankcc.public()\n",
"\n",
" self.prv = python_bitbankcc.private(\n",
" os.environ['BITBANK_API_KEY'],\n",
" os.environ['BITBANK_API_SECRET']\n",
" )\n",
"\n",
" self.status = status\n",
" self.portfolio = self.get_portfolio()\n",
" self.last_transaction = None\n",
"\n",
" def __enter__(self):\n",
" self.fsh = open('sample-history.txt', 'a', 1)\n",
" self.fth = open('transaction-history.txt', 'a', 1)\n",
Expand All @@ -308,7 +319,81 @@
" '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",
" def get_portfolio(self):\n",
" return Portfolio([\n",
" (asset.get('asset', ''), Decimal(asset.get('onhand_amount', '0'))) for asset in self.prv.get_asset().get('assets', [])\n",
" ])\n",
"\n",
" def estimate_status(self):\n",
" old_portfolio = self.portfolio\n",
" new_portfolio = self.get_portfolio()\n",
" self.portfolio = new_portfolio\n",
"\n",
" old_fiat_money = old_portfolio.jpy\n",
" old_amount = old_portfolio.eth\n",
" new_fiat_money = new_portfolio.jpy\n",
" new_amount = new_portfolio.eth\n",
"\n",
" if old_fiat_money > new_fiat_money and old_amount < new_amount:\n",
" amount = new_amount - old_amount\n",
" fiat_price = (old_fiat_money - new_fiat_money) / amount\n",
"\n",
" if self.status.now_buy_fiat_price is None:\n",
" return self.status\n",
" now_buy_fiat_price = Decimal(self.status.now_buy_fiat_price)\n",
" if abs(fiat_price - now_buy_fiat_price) / now_buy_fiat_price > Decimal(50/100):\n",
" return self.status\n",
"\n",
" new_status = self.estimate_status_by_buying(\n",
" int( amount / Decimal(repr(self.status.trade_unit)) ),\n",
" float( fiat_price )\n",
" )\n",
"\n",
" new_status.update(\n",
" status = {\n",
" 'sold_unit_amount': 0,\n",
" 'please_buy_unit_amount': 0\n",
" }\n",
" )\n",
"\n",
" return new_status\n",
"\n",
" if old_fiat_money < new_fiat_money and old_amount > new_amount:\n",
" amount = old_amount - new_amount\n",
" fiat_price = (new_fiat_money - old_fiat_money) / amount\n",
"\n",
" if self.status.now_sell_fiat_price is None:\n",
" return self.status\n",
" now_sell_fiat_price = Decimal(self.status.now_sell_fiat_price)\n",
" if abs(fiat_price - now_sell_fiat_price) / now_sell_fiat_price > Decimal(50/100):\n",
" return self.status\n",
"\n",
" new_status = self.estimate_status_by_selling(\n",
" int( amount / Decimal(repr(self.status.trade_unit)) ),\n",
" float( fiat_price )\n",
" )\n",
"\n",
" new_status.update(\n",
" status = {\n",
" 'please_buy_unit_amount': 0,\n",
" 'please_sell_unit_amount': 0\n",
" }\n",
" )\n",
"\n",
" if new_status.bought_unit_amount == 0:\n",
" new_status.update(\n",
" status = {\n",
" 'trade_count': status.trade_count + 1,\n",
" 'buy_count': 0,\n",
" 'sell_count': 0\n",
" }\n",
" )\n",
"\n",
" return new_status\n",
"\n",
" return self.status\n",
"\n",
" def buy_secretly(self, unit_amount, fiat_price=None):\n",
" if unit_amount <= 0:\n",
" return\n",
" if fiat_price is None:\n",
Expand All @@ -319,6 +404,24 @@
" pair='eth_jpy', price=str(fiat_price), amount=str(amount), side='buy', order_type='market'\n",
" )\n",
"\n",
" def buy(self, unit_amount, fiat_price=None):\n",
" if unit_amount <= 0:\n",
" return\n",
" if fiat_price is None:\n",
" fiat_price = self.status.now_buy_fiat_price\n",
"\n",
" self.buy_secretly(unit_amount, fiat_price)\n",
"\n",
" return self.estimate_status_by_buying(unit_amount, fiat_price)\n",
"\n",
" def estimate_status_by_buying(self, unit_amount, fiat_price=None):\n",
" if unit_amount <= 0:\n",
" return\n",
" if fiat_price is None:\n",
" fiat_price = self.status.now_buy_fiat_price\n",
"\n",
" amount = self.status.trade_unit * unit_amount\n",
"\n",
" old_status = self.status\n",
" new_status = copy.deepcopy(old_status)\n",
"\n",
Expand All @@ -339,7 +442,7 @@
"\n",
" return new_status\n",
"\n",
" def sell(self, unit_amount, fiat_price=None):\n",
" def sell_secretly(self, unit_amount, fiat_price=None):\n",
" if unit_amount <= 0:\n",
" return\n",
" if fiat_price is None:\n",
Expand All @@ -350,6 +453,24 @@
" pair='eth_jpy', price=str(fiat_price), amount=str(amount), side='sell', order_type='market'\n",
" )\n",
"\n",
" def sell(self, unit_amount, fiat_price=None):\n",
" if unit_amount <= 0:\n",
" return\n",
" if fiat_price is None:\n",
" fiat_price = self.status.now_sell_fiat_price\n",
"\n",
" self.sell_secretly(unit_amount, fiat_price)\n",
"\n",
" return self.estimate_status_by_selling(unit_amount, fiat_price)\n",
"\n",
" def estimate_status_by_selling(self, unit_amount, fiat_price=None):\n",
" if unit_amount <= 0:\n",
" return\n",
" if fiat_price is None:\n",
" fiat_price = self.status.now_sell_fiat_price\n",
"\n",
" amount = self.status.trade_unit * unit_amount\n",
"\n",
" old_status = self.status\n",
" new_status = copy.deepcopy(old_status)\n",
"\n",
Expand Down Expand Up @@ -450,21 +571,42 @@
"import time\n",
"from decimal import Decimal\n",
"with BookKeeper(status) as bookkeeper:\n",
" from unittest.mock import Mock\n",
" bookkeeper.prv = Mock()\n",
"# from unittest.mock import Mock\n",
"# bookkeeper.prv.order = 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",
" new_status = bookkeeper.estimate_status()\n",
" if new_status is not status:\n",
" bookkeeper.fth.write(f'{new_status}\\n')\n",
" new_status.write()\n",
"\n",
" send_slack(\n",
" f'{bookkeeper.last_transaction}'\n",
" f'BY {new_status.get_robot_title()}',\n",
" 'Power by https://jhub.name/', 'good' if new_status.total_gained_fiat_money > 0 else 'danger'\n",
" )\n",
"\n",
" send_slack(\n",
" f'{new_status} => Support level is {MIN_UNIT_CC_INIT_TRADE_JPY} JPY.',\n",
" 'Power by https://jhub.name/', 'good' if new_status.get_total_gain_fiat_money() > 0 else 'danger'\n",
" )\n",
"\n",
" if new_status.bought_unit_amount == 0 and new_status.total_gained_fiat_money > MAX_GAIN_JPY << 2 and not isinstance(bookkeeper.prv, Mock):\n",
" from unittest.mock import Mock\n",
" bookkeeper.prv = Mock()\n",
" send_slack(\n",
" f'{new_status.robot_name} is turned to Mock', 'Power by https://jhub.name/', 'good'\n",
" )\n",
"\n",
"# if len(bought_unit_amounts) > 0:\n",
"# bought_unit_amount_before = status.bought_unit_amount\n",
" if new_status.total_gained_fiat_money < -MAX_TOTAL_LOST_JPY:\n",
" break\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 new_status.total_gained_fiat_money == status.total_gained_fiat_money:\n",
" time.sleep(SAMPLE_INTERVAL / TEST_RATIO)\n",
" else:\n",
" time.sleep(new_status.cooling_time/TEST_RATIO)\n",
" status.cooling_time = HAPPY_COOLING_TIME\n",
"\n",
" status.update(new_status)\n",
" status.update(bookkeeper.get_price())\n",
"\n",
" if status.sample_number % TRADE_RATE == 0 and status.bought_average_fiat_price is not None and status.now_sell_fiat_price > status.bought_average_fiat_price:\n",
Expand Down Expand Up @@ -507,49 +649,8 @@
" status.cooling_time = SAD_COOLING_TIME\n",
"\n",
" if status.please_sell_unit_amount > 0:\n",
" new_status = bookkeeper.sell(status.please_sell_unit_amount)\n",
" bookkeeper.fth.write(f'{new_status}\\n')\n",
"\n",
" bookkeeper.sell_secretly(status.please_sell_unit_amount)\n",
" bookkeeper.fsh.write(f'{status}\\n')\n",
"\n",
" send_slack(\n",
" f'{bookkeeper.last_transaction}'\n",
" f'BY {new_status.get_robot_title()}',\n",
" 'Power by https://jhub.name/', 'good' if new_status.total_gained_fiat_money > 0 else 'danger'\n",
" )\n",
"\n",
" status.update( status = new_status )\n",
" status.update(\n",
" status = {\n",
" 'please_buy_unit_amount': 0,\n",
" 'please_sell_unit_amount': 0\n",
" }\n",
" )\n",
"\n",
" if status.bought_unit_amount == 0:\n",
" status.update(\n",
" status = {\n",
" 'trade_count': status.trade_count + 1,\n",
" 'buy_count': 0,\n",
" 'sell_count': 0\n",
" }\n",
" )\n",
"\n",
" if status.bought_unit_amount == 0 and status.total_gained_fiat_money > MAX_GAIN_JPY << 2 and not isinstance(bookkeeper.prv, Mock):\n",
" from unittest.mock import Mock\n",
" bookkeeper.prv = Mock()\n",
" send_slack(\n",
" f'{status.robot_name} is turned to Mock', 'Power by https://jhub.name/', 'good'\n",
" )\n",
"\n",
" status.write()\n",
"\n",
" if status.total_gained_fiat_money < -MAX_TOTAL_LOST_JPY:\n",
" break\n",
"\n",
" status.sample_number += 1\n",
" time.sleep(status.cooling_time/TEST_RATIO)\n",
" status.cooling_time = HAPPY_COOLING_TIME\n",
" continue\n",
"\n",
" if status.used_fiat_money < INIT_BUY_JPY and INIT_BUY_JPY - status.used_fiat_money <= (MAX_TRADED_JPY - status.used_fiat_money) * 0.75 \\\n",
Expand All @@ -566,30 +667,24 @@
" status.please_buy_unit_amount = trade_unit_amount\n",
"\n",
" if status.please_buy_unit_amount > 0:\n",
" new_status = bookkeeper.buy(status.please_buy_unit_amount)\n",
" bookkeeper.fth.write(f'{new_status}\\n')\n",
" bookkeeper.buy_secretly(status.please_buy_unit_amount)\n",
" bookkeeper.fsh.write(f'{status}\\n')\n",
" continue\n",
"\n",
" status.update( status = new_status )\n",
" status.update(\n",
" status = {\n",
" 'sold_unit_amount': 0,\n",
" 'please_buy_unit_amount': 0\n",
" }\n",
" )\n",
" elif status.sample_number % TRADE_RATE == 0:\n",
" bookkeeper.fsh.write(f'{status}\\n')\n",
"\n",
" if status.sample_number % TRADE_RATE == 0:\n",
" bookkeeper.fth.write(f'{status}\\n')\n",
"\n",
" bookkeeper.fsh.write(f'{status}\\n')\n",
" if status.sample_number % BACKUP_RATE == 0:\n",
" status.write()\n",
"\n",
" if status.sample_number % NOTIFY_RATE == 0:\n",
" send_slack(\n",
" f'{status} => Support level is {MIN_UNIT_CC_INIT_TRADE_JPY} JPY.',\n",
" 'Power by https://jhub.name/', 'good' if status.get_total_gain_fiat_money() > 0 else 'danger'\n",
" )\n",
"\n",
" if status.sample_number % BACKUP_RATE == 0:\n",
" status.write()\n",
"\n",
" status.sample_number += 1\n",
" time.sleep(SAMPLE_INTERVAL / TEST_RATIO)"
]
Expand Down

0 comments on commit dd42747

Please sign in to comment.