Merge branch 'refactor' of ssh://giugl.io.gitea:10022/peperunas/gkaching into refactor

This commit is contained in:
Giulio De Pasquale 2020-12-07 21:38:22 +00:00
commit dcd91eaab8
4 changed files with 76 additions and 67 deletions

View File

@ -8,6 +8,14 @@ from bfxbot.models import SymbolStatus, Ticker, EventHandler, Strategy
class BfxBot: class BfxBot:
def __init__(self, api_key: str, api_secret: str, tick_duration: int = 1): def __init__(self, api_key: str, api_secret: str, tick_duration: int = 1):
if api_key is None:
print("API_KEY is not set!")
raise ValueError
if api_secret is None:
print("API_SECRET is not set!")
raise ValueError
self.bfx: BfxWrapper = BfxWrapper(api_key, api_secret) self.bfx: BfxWrapper = BfxWrapper(api_key, api_secret)
self.status: Dict[Symbol, SymbolStatus] = {} self.status: Dict[Symbol, SymbolStatus] = {}
self.ticker: Ticker = Ticker(tick_duration) self.ticker: Ticker = Ticker(tick_duration)

56
main.py
View File

@ -485,70 +485,34 @@
# if __name__ == "__main__": # if __name__ == "__main__":
# asyncio.run(Screen.wrapper(main)) # asyncio.run(Screen.wrapper(main))
import asyncio import asyncio
import shutil import os
from typing import List
from asciimatics.screen import Screen, ManagedScreen import dotenv
from asciimatics.widgets import Frame, Layout, Text
from bfxapi import Position
from bfxbot import BfxBot from bfxbot import BfxBot
import dotenv
import os
import bfxapi
from bfxbot.currency import Symbol from bfxbot.currency import Symbol
from bfxbot.models import Strategy, SymbolStatus, PositionState, Event, EventKind from bfxbot.models import PositionState
from bfxbot.utils import TAKER_FEE, net_pl_percentage
from strategy import TrailingStopStrategy from strategy import TrailingStopStrategy
dotenv.load_dotenv() dotenv.load_dotenv()
async def main():
API_KEY = os.getenv("API_KEY") API_KEY = os.getenv("API_KEY")
API_SECRET = os.getenv("API_SECRET") API_SECRET = os.getenv("API_SECRET")
if API_KEY is None: bot = BfxBot(api_key=API_KEY, api_secret=API_SECRET)
print("API_KEY is not set! Set the var in the .env file.")
return
if API_SECRET is None:
print("API_SECRET is not set! Set the var in the .env file.")
return
bot = BfxBot(api_key=API_KEY, api_secret=API_SECRET, tick_duration=20)
strategy = TrailingStopStrategy() strategy = TrailingStopStrategy()
bot.set_strategy(Symbol.BTC, strategy) bot.set_strategy(Symbol.BTC, strategy)
eh = bot.event_handler(Symbol.BTC) eh = bot.event_handler(Symbol.BTC)
@eh.on_state(PositionState.PROFIT)
def on_min_profit(ss, pw):
print("Minimum profit!")
async def main():
await bot.start() await bot.start()
while True: while True:
await bot_loop(bot)
@ManagedScreen
async def bot_loop(bot: BfxBot, screen: Screen = None):
prepare_tui(screen)
screen.play()
await bot.update() await bot.update()
def prepare_tui(screen: Screen):
w, h = shutil.get_terminal_size()
frame = Frame(screen, w, h, has_border=False)
info_layout = Layout([1])
graph_layout = Layout([1])
footer_layout = Layout([1])
frame.add_layout(info_layout)
frame.add_layout(graph_layout)
frame.add_layout(footer_layout)
info_layout.add_widget(Text(label="Test"))
if __name__ == '__main__': if __name__ == '__main__':
asyncio.run(main()) asyncio.run(main())

View File

@ -1,5 +1,2 @@
asciimatics==1.12.0 python-dotenv~=0.15.0
asyncio==3.4.3 sympy~=1.7
playsound==1.2.2
termcolor==1.1.0
termplotlib==0.3.2

View File

@ -1,22 +1,60 @@
from typing import List from typing import List
from bfxapi import Position import sympy.abc
from sympy import Point, solve
from bfxbot.models import Strategy, PositionState, SymbolStatus, Event, EventKind from bfxbot.models import Strategy, PositionState, SymbolStatus, Event, EventKind
from bfxbot.utils import TAKER_FEE, net_pl_percentage from bfxbot.utils import TAKER_FEE, net_pl_percentage
class Position(object):
def __init__(self):
self.id = None
self.profit_loss_percentage = None
pass
class SquaredTrailingStop:
def __init__(self, p_min: Point, p_max: Point):
a = sympy.abc.a
b = sympy.abc.b
c = sympy.abc.c
self.p_min = p_min
self.p_max = p_max
e1 = 2 * a * (p_max.x + b)
e2 = a * (p_min.x + b)**2 + c - p_min.y
e3 = a * (p_max.x + b)**2 + c - p_max.y
s = solve([e1, e2, e3])[0]
self.a, self.b, self.c = s[a], s[b], s[c]
def y(self, x):
def inter_y(x):
return self.a * (x + self.b)**2 + self.c
if x < self.p_min.x:
return self.p_min.y
elif x > self.p_max.x:
return self.p_max.y
else:
return inter_y(x)
def profit(self, x):
if x < self.p_min.x:
return 0
return x - self.y(x)
class TrailingStopStrategy(Strategy): class TrailingStopStrategy(Strategy):
BREAK_EVEN_PERC = TAKER_FEE BREAK_EVEN_PERC = TAKER_FEE
MIN_PROFIT_PERC = TAKER_FEE * 2.5 MIN_PROFIT_PERC = BREAK_EVEN_PERC + 0.3
GOOD_PROFIT_PERC = MIN_PROFIT_PERC * 1.5 GOOD_PROFIT_PERC = MIN_PROFIT_PERC * 2.5
MAX_LOSS_PERC = -3.75 MAX_LOSS_PERC = -3.75
OFFER_PERC = 0.01 OFFER_PERC = 0.005
TRAIL_STOP_PERCENTAGES = { TRAILING_STOP = SquaredTrailingStop(Point(MIN_PROFIT_PERC, MIN_PROFIT_PERC/3*2), Point(GOOD_PROFIT_PERC, 0.1))
PositionState.MINIMUM_PROFIT: 0.27,
PositionState.PROFIT: 0.14
}
def position_on_tick(self, position: Position, ss: SymbolStatus) -> (PositionState, List[Event]): def position_on_tick(self, position: Position, ss: SymbolStatus) -> (PositionState, List[Event]):
events = [] events = []
@ -51,3 +89,5 @@ class TrailingStopStrategy(Strategy):
events.append(Event(EventKind.CLOSE_POSITION, position.id, ss.current_tick)) events.append(Event(EventKind.CLOSE_POSITION, position.id, ss.current_tick))
return state, events return state, events