add WMA algorithm with bitbank bot
This commit is contained in:
parent
37840311e0
commit
ecb9ad08e1
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
__pycache__/
|
||||
secret.json
|
2
algorithm/__init__.py
Normal file
2
algorithm/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
from algorithm.wma import WMA
|
||||
from algorithm.status import Status
|
4
algorithm/status.py
Normal file
4
algorithm/status.py
Normal file
@ -0,0 +1,4 @@
|
||||
class Status:
|
||||
def __init__(self):
|
||||
self.price = 0
|
||||
self.candles = {"1m": [], "1h": []}
|
22
algorithm/wma.py
Normal file
22
algorithm/wma.py
Normal file
@ -0,0 +1,22 @@
|
||||
class WMA:
|
||||
def __init__(self, unit, period, width):
|
||||
self._unit = unit
|
||||
self._period = period
|
||||
self._width = width
|
||||
|
||||
def judge(self, status):
|
||||
cands = status.candles[self._unit]
|
||||
sum = 0
|
||||
den = 0
|
||||
for i in range(min(self._period-1, len(cands)-1)):
|
||||
sum += cands[i+1][3] * (i+1)
|
||||
den += i+1
|
||||
avg = sum / den
|
||||
price = cands[0][3]
|
||||
|
||||
width = price * self._width
|
||||
diff = price - avg
|
||||
if diff < 0:
|
||||
return max(-1, diff/width) # sell
|
||||
else:
|
||||
return min(1, diff/width) # buy
|
146
bitbank.py
Normal file
146
bitbank.py
Normal file
@ -0,0 +1,146 @@
|
||||
import datetime
|
||||
import json
|
||||
import python_bitbankcc
|
||||
import random
|
||||
import sys
|
||||
import time
|
||||
|
||||
import algorithm
|
||||
|
||||
|
||||
FETCH_INTERVAL = 5
|
||||
|
||||
status = {}
|
||||
|
||||
def init():
|
||||
try:
|
||||
sec = json.load(open("secret.json"))
|
||||
sec = sec["bitbank"]
|
||||
pub = python_bitbankcc.public()
|
||||
pri = python_bitbankcc.private(sec["key"], sec["secret"])
|
||||
except Exception as e:
|
||||
print("failed to initialize bitbank features: ", e)
|
||||
return []
|
||||
|
||||
procs = []
|
||||
procs.append(Fetcher(pub, "btc_jpy"))
|
||||
procs.append(Fetcher(pub, "eth_jpy"))
|
||||
procs.append(Fetcher(pub, "matic_jpy"))
|
||||
procs.append(Proc(pri, "btc_jpy", 5000, algorithm.WMA("1h", 8, 0.01), 10*60))
|
||||
procs.append(Proc(pri, "eth_jpy", 5000, algorithm.WMA("1h", 8, 0.01), 10*60))
|
||||
procs.append(Proc(pri, "matic_jpy", 5000, algorithm.WMA("1m", 8, 0.01), 5))
|
||||
return procs
|
||||
|
||||
|
||||
class Fetcher:
|
||||
def __init__(self, pub, pair):
|
||||
self._last_update = 0
|
||||
|
||||
self._pub = pub
|
||||
self._pair = pair
|
||||
|
||||
def tick(self):
|
||||
if time.time()-self._last_update < FETCH_INTERVAL:
|
||||
return
|
||||
try:
|
||||
st = algorithm.Status()
|
||||
|
||||
st.candles["1m"] = self._get_candle("1min")
|
||||
st.candles["1h"] = self._get_candle("1hour")
|
||||
|
||||
st.price = st.candles["1m"][0][3]
|
||||
|
||||
global status
|
||||
status[self._pair] = st
|
||||
except Exception as e:
|
||||
print("fetce error:", e)
|
||||
return
|
||||
|
||||
def _get_candle(self, unit):
|
||||
data = self._pub.get_candlestick(
|
||||
self._pair,
|
||||
unit,
|
||||
datetime.datetime.now().strftime("%Y%m%d"))
|
||||
data = data["candlestick"][0]["ohlcv"]
|
||||
|
||||
ret = []
|
||||
for i in range(min(30, len(data))):
|
||||
j = len(data)-i-1
|
||||
ret.append([float(data[j][0]), float(data[j][1]), float(data[j][2]), float(data[j][3])])
|
||||
return ret
|
||||
|
||||
|
||||
class Proc:
|
||||
def __init__(self, pri, pair, asset, algo, interval):
|
||||
self._pri = pri
|
||||
self._pair = pair
|
||||
|
||||
self._last_update = 0
|
||||
self._now = 0
|
||||
|
||||
self._bsi = 0
|
||||
self._algo = algo
|
||||
self._interval = interval
|
||||
|
||||
self._buy_price = None
|
||||
|
||||
self._asset = asset
|
||||
|
||||
def tick(self):
|
||||
self._now = time.time()
|
||||
if self._now-self._last_update > self._interval:
|
||||
self._update()
|
||||
self._last_update = self._now
|
||||
|
||||
def _update(self):
|
||||
global status
|
||||
st = status[self._pair]
|
||||
|
||||
pbsi = self._bsi
|
||||
bsi = self._algo.judge(status[self._pair])
|
||||
self._bsi = bsi
|
||||
|
||||
print(f"[bitbank: {self._pair}] BSI {pbsi} -> {bsi}")
|
||||
if bsi*pbsi < 0:
|
||||
if bsi > 0:
|
||||
try:
|
||||
amount = self._asset/st.price
|
||||
self._order_market(amount, "buy")
|
||||
self._buy_price = st.price
|
||||
print(f"[bitbank: {self._pair}] <BUY> amount: {amount}")
|
||||
except Exception as e:
|
||||
self._buy_price = None
|
||||
print(f"[bitbank: {self._pair}] buy error", e)
|
||||
elif self._buy_price is not None:
|
||||
try:
|
||||
amount = self._asset/self._buy_price
|
||||
self._order_market(self._asset/self._buy_price, "sell")
|
||||
print(f"[bitbank: {self._pair}] <SELL> amount: {amount}")
|
||||
except Exception as e:
|
||||
print(f"[bitbank: {self._pair}] sell error", e)
|
||||
|
||||
def _order_market(self, amount, sell_or_buy):
|
||||
self._pri.order(self._pair, None, str(amount), sell_or_buy, "market")
|
||||
|
||||
def _order_limit(self, price, sell_or_buy):
|
||||
try_price = price
|
||||
for i in range(10):
|
||||
amount = self._asset/price
|
||||
order = self._pri.order(self._pair, str(price), str(amount), sell_or_buy, "limit", True)
|
||||
time.sleep(.1)
|
||||
|
||||
order = self._pri.get_order(self._pair, order["order_id"])
|
||||
if order["status"] == "UNFILLED":
|
||||
return
|
||||
|
||||
move = random.random()*10+1
|
||||
if sell_or_buy == "sell":
|
||||
price = price-move
|
||||
else:
|
||||
price = price+move
|
||||
|
||||
if sell_or_buy == "sell":
|
||||
self._pri.order(self._pair, None, str(amount), sell_or_buy, "market")
|
||||
print(f"[bitbank: {self._pair}] <MARKET-SELL> amount: {amount}")
|
||||
else:
|
||||
raise Exception("tried 10 times.... X(")
|
120
main.py
Normal file
120
main.py
Normal file
@ -0,0 +1,120 @@
|
||||
import multiprocessing
|
||||
import os
|
||||
import signal
|
||||
import time
|
||||
|
||||
import bitbank
|
||||
|
||||
|
||||
def main():
|
||||
procs = [*bitbank.init()]
|
||||
while True:
|
||||
for i in range(len(procs)):
|
||||
procs[i].tick()
|
||||
time.sleep(1)
|
||||
|
||||
def on_exit(sig):
|
||||
print(f"received {sig}")
|
||||
|
||||
proc = multiprocessing.Process(target = main)
|
||||
proc.start()
|
||||
signal.signal(signal.SIGTERM, on_exit)
|
||||
signal.pause()
|
||||
proc.join()
|
||||
|
||||
|
||||
# while True:
|
||||
# print("start tick")
|
||||
#
|
||||
# # ---- get assets
|
||||
# assets = pri.get_asset()["assets"]
|
||||
# onhand = {}
|
||||
# locked = {}
|
||||
# for i in range(len(assets)):
|
||||
# coin = assets[i]["asset"]
|
||||
# onhand[coin] = float(assets[i]["onhand_amount"])
|
||||
# locked[coin] = float(assets[i]["locked_amount"])
|
||||
#
|
||||
# # ---- get current price
|
||||
# candles = pub.get_candlestick("btc_jpy", "1min", now.strftime("%Y%m%d"))["candlestick"][0]["ohlcv"];
|
||||
# latest_candle = candles[len(candles)-1]
|
||||
# begin = int(latest_candle[0])
|
||||
# high = int(latest_candle[1])
|
||||
# low = int(latest_candle[2])
|
||||
# end = int(latest_candle[3])
|
||||
#
|
||||
# # ---- cancel existing orderes
|
||||
# prev_orders = pri.get_active_orders("btc_jpy")["orders"]
|
||||
# cancel_orders = []
|
||||
# for i in range(len(prev_orders)):
|
||||
# id = prev_orders[i]["order_id"]
|
||||
# status = prev_orders[i]["status"]
|
||||
# side = prev_orders[i]["side"]
|
||||
# price = int(prev_orders[i]["price"])
|
||||
#
|
||||
# if status == "UNFILLED":
|
||||
# diff = abs(end-price)/end
|
||||
# if side == "buy":
|
||||
# if diff < -0.0005:
|
||||
# cancel_orders.append(str(id))
|
||||
# elif side == "sell":
|
||||
# if diff > 0.003:
|
||||
# cancel_orders.append(str(id))
|
||||
#
|
||||
# if len(cancel_orders) > 0:
|
||||
# pri.cancel_orders("btc_jpy", cancel_orders)
|
||||
# print("cancelled", len(cancel_orders), "orders")
|
||||
# if len(prev_orders)-len(cancel_orders) > 8:
|
||||
# print("skip making an order because there are too many orderes")
|
||||
# time.sleep(30)
|
||||
# continue
|
||||
#
|
||||
# # ---- get transactions
|
||||
# trans = pub.get_transactions("btc_jpy")["transactions"]
|
||||
# buy_min = low
|
||||
# sell_max = high
|
||||
# for i in range(len(trans)):
|
||||
# exec_at = datetime.datetime.fromtimestamp(trans[i]["executed_at"]/1000)
|
||||
# side = trans[i]["side"]
|
||||
# price = int(trans[i]["price"])
|
||||
# if now-exec_at < datetime.timedelta(minutes=1):
|
||||
# if side == "buy":
|
||||
# buy_min = min(buy_min, price)
|
||||
# elif side == "sell":
|
||||
# sell_max = max(sell_max, price)
|
||||
#
|
||||
# # ---- make an order
|
||||
# buy_coe = 0.5
|
||||
# ben_coe = 0.8
|
||||
#
|
||||
# diff = (end-begin)/end
|
||||
# if diff > 0.002:
|
||||
# buy_coe -= clamp(100*diff/end, 0, 1)*0.2
|
||||
# elif diff < -0.002:
|
||||
# buy_coe += clamp(100*diff, 0, 1)*0.2
|
||||
#
|
||||
# print("buy-min:", buy_min, "| sell-max:", sell_max, "| diff:", sell_max-buy_min)
|
||||
# diff = sell_max-buy_min
|
||||
# avg = (sell_max+buy_min)/2
|
||||
#
|
||||
# buy_price = avg - diff*buy_coe*ben_coe
|
||||
# sell_price = avg + diff*(1-buy_coe)*ben_coe
|
||||
#
|
||||
# buy_jpy = max((onhand["jpy"]-locked["jpy"])*0.1, (onhand["btc"]-locked["btc"])*end*0.1)
|
||||
# buy_btc = buy_jpy/buy_price
|
||||
# sell_jpy = buy_btc*sell_price
|
||||
# sell_btc = buy_btc
|
||||
#
|
||||
# try:
|
||||
# pri.order("btc_jpy", str(buy_price), str(buy_btc), "buy", "limit", True)
|
||||
# print("[buy] btc:", buy_btc, "| jpy:", -buy_jpy, "| price:", buy_price)
|
||||
# except Exception as e:
|
||||
# print(e)
|
||||
#
|
||||
# try:
|
||||
# pri.order("btc_jpy", str(sell_price), str(sell_btc), "sell", "limit", True)
|
||||
# print("[sel] btc:", -sell_btc, "| jpy:", sell_jpy, "| price:", sell_price)
|
||||
# except Exception as e:
|
||||
# print(e)
|
||||
#
|
||||
# time.sleep(10)
|
2
requirements.txt
Normal file
2
requirements.txt
Normal file
@ -0,0 +1,2 @@
|
||||
git+https://github.com/bitbankinc/python-bitbankcc@3aee8a6ef9d4616e11f044c2a1574ec389671675#egg=python-bitbankcc
|
||||
requests
|
6
secret.json.default
Normal file
6
secret.json.default
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"bitbank": {
|
||||
"key": "your key",
|
||||
"secret": "your secret"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user