4 Commits
0.0.5 ... 0.0.7

Author SHA1 Message Date
c1835ca4eb Info and log fixes
All checks were successful
Build and Push Docker Image / build-and-push (release) Successful in 1m16s
2025-05-26 11:20:39 +03:00
f27df7b1b8 Bot start/stop
All checks were successful
Build and Push Docker Image / build-and-push (release) Successful in 1m27s
2025-05-26 10:59:37 +03:00
7fbd2887b7 Small fixes 2025-05-25 23:26:35 +03:00
262cef3f2f Updated docs 2025-05-22 14:42:28 +03:00
7 changed files with 51 additions and 21 deletions

View File

@ -27,6 +27,8 @@ services:
DEMOTRADING: "False" DEMOTRADING: "False"
LOOPSLEEPTIME: "1" LOOPSLEEPTIME: "1"
SHOWEXTRADEBUGLOGS: "False" SHOWEXTRADEBUGLOGS: "False"
volumes:
- ./data:/app/data
restart: unless-stopped restart: unless-stopped
``` ```
### After the basic pre-setup: ### After the basic pre-setup:

View File

@ -27,6 +27,8 @@ services:
DEMOTRADING: "False" DEMOTRADING: "False"
LOOPSLEEPTIME: "1" LOOPSLEEPTIME: "1"
SHOWEXTRADEBUGLOGS: "False" SHOWEXTRADEBUGLOGS: "False"
volumes:
- ./data:/app/data
restart: unless-stopped restart: unless-stopped
``` ```
### После базовой развёртки выполните следующие шаги: ### После базовой развёртки выполните следующие шаги:

View File

@ -12,4 +12,6 @@ services:
DEMOTRADING: "False" DEMOTRADING: "False"
LOOPSLEEPTIME: "1" LOOPSLEEPTIME: "1"
SHOWEXTRADEBUGLOGS: "False" SHOWEXTRADEBUGLOGS: "False"
volumes:
- ./data:/app/data
restart: unless-stopped restart: unless-stopped

View File

@ -11,7 +11,7 @@ def setStartTime():
startTime = time.time() startTime = time.time()
def getPnL(pair): def getPnL(pair):
with open("tradingLog.log", "r") as f: with open("./data/tradingLog.log", "r") as f:
lines = f.readlines() lines = f.readlines()
logEntries = [] logEntries = []
@ -25,7 +25,7 @@ def getPnL(pair):
strategyStartTime = None strategyStartTime = None
for timestamp, message in logEntries: for timestamp, message in logEntries:
if message == f"Starting strategy with {pair}": if message == (f"Starting strategy with {pair}"):
strategyStartTime = timestamp strategyStartTime = timestamp
if not strategyStartTime: if not strategyStartTime:

View File

@ -59,7 +59,7 @@ class tradingData:
self.orderSize = orderSize self.orderSize = orderSize
self.priceDecimals, self.qtyDecimals, self.minimumQty = self.getFilters(pair) self.priceDecimals, self.qtyDecimals, self.minimumQty = self.getFilters(pair)
self.previousPrice = -1 self.previousPrice = -1
self.counter = 0 self.orderCounter = 0
def getBalance(self, pair): def getBalance(self, pair):
@ -147,6 +147,7 @@ class tradingData:
stopLoss = str(sl), stopLoss = str(sl),
tpslMode = "Full" tpslMode = "Full"
) )
self.orderCounter += 1
orderID = response.get('result').get('orderId') orderID = response.get('result').get('orderId')
generalLogger.info(f"Placed oder on {self.pair} with TP {tp}; SL {sl}") generalLogger.info(f"Placed oder on {self.pair} with TP {tp}; SL {sl}")
@ -209,10 +210,14 @@ class tradingData:
j['long'] = False j['long'] = False
j['longIDs'] = ['-1', '-1', '-1'] j['longIDs'] = ['-1', '-1', '-1']
generalLogger.info(f"Long order on {self.pair} level {j['price']} triggered TP/SL") generalLogger.info(f"Long order on {self.pair} level {j['price']} triggered TP/SL")
tradingLogger.info(f"Long order on {self.pair} level {j['price']} triggered TP/SL")
self.orderCounter -= 1
if orderID in shortIDs: if orderID in shortIDs:
j['short'] = False j['short'] = False
j['shortIDs'] = ['-1', '-1', '-1'] j['shortIDs'] = ['-1', '-1', '-1']
generalLogger.info(f"Short order on {self.pair} level {j['price']} triggered TP/SL") generalLogger.info(f"Short order on {self.pair} level {j['price']} triggered TP/SL")
tradingLogger.info(f"Short order on {self.pair} level {j['price']} triggered TP/SL")
self.orderCounter -= 1
if orderStatus == 'Filled': if orderStatus == 'Filled':
for j in self.levels: for j in self.levels:
longIDs = j['longIDs'] longIDs = j['longIDs']
@ -221,6 +226,7 @@ class tradingData:
generalLogger.info(f"Long order on {self.pair} level {j['price']} filled with P&L {i['closedPnl']} and qty {i['qty']}") generalLogger.info(f"Long order on {self.pair} level {j['price']} filled with P&L {i['closedPnl']} and qty {i['qty']}")
tradingLogger.info(f"Long order on {self.pair} level {j['price']} filled with P&L {i['closedPnl']} and qty {i['qty']}") tradingLogger.info(f"Long order on {self.pair} level {j['price']} filled with P&L {i['closedPnl']} and qty {i['qty']}")
if orderID in shortIDs: if orderID in shortIDs:
generalLogger.info(f"Short order on {self.pair} level {j['price']} filled with P&L {i['closedPnl']} and qty {i['qty']}")
tradingLogger.info(f"Short order on {self.pair} level {j['price']} filled with P&L {i['closedPnl']} and qty {i['qty']}") tradingLogger.info(f"Short order on {self.pair} level {j['price']} filled with P&L {i['closedPnl']} and qty {i['qty']}")
@ -244,6 +250,7 @@ async def getClient(apiKey, apiSecret, testnet, demoTrading):
async def strategy(pair: str, params): async def strategy(pair: str, params):
generalLogger.info('Starting strategy with ' + pair) generalLogger.info('Starting strategy with ' + pair)
tradingLogger.info('Starting strategy with ' + pair)
paramsDict = await jsonProcessing.parseParams(params) paramsDict = await jsonProcessing.parseParams(params)

View File

@ -32,6 +32,9 @@ async def parseParams(params):
# Returnes dictionary of string params as paramsLines in options # Returnes dictionary of string params as paramsLines in options
paramsList = params.split() paramsList = params.split()
paramsDict = {} paramsDict = {}
if len(paramsList) != len(options.paramsLines):
return -1
for i in range(len(options.paramsLines)): for i in range(len(options.paramsLines)):
paramsDict[options.paramsLines[i]] = paramsList[i] paramsDict[options.paramsLines[i]] = paramsList[i]
return paramsDict return paramsDict

View File

@ -27,10 +27,11 @@ import strings
import options import options
async def set_commands(): async def setCommands():
commands = [BotCommand(command='start', description='Старт'), commands = [BotCommand(command='start', description='Старт'),
BotCommand(command='help', description='Инструкция'), BotCommand(command='help', description='Инструкция'),
BotCommand(command='info', description='Статус'), BotCommand(command='info', description='Информация о стратегиях'),
BotCommand(command='status', description='Статус'),
BotCommand(command='strategy', description='Запустить стратегию'), BotCommand(command='strategy', description='Запустить стратегию'),
BotCommand(command='stop', description='Остановить стратегию') BotCommand(command='stop', description='Остановить стратегию')
] ]
@ -51,8 +52,8 @@ bot = Bot(
default=DefaultBotProperties(parse_mode=ParseMode.HTML), default=DefaultBotProperties(parse_mode=ParseMode.HTML),
) )
strategy_router = Router() strategyRouter = Router()
stop_router = Router() stopRouter = Router()
@dp.message(Command("start")) @dp.message(Command("start"))
@ -86,13 +87,13 @@ async def commandInfo(message: Message) -> None:
await message.answer(msgText) await message.answer(msgText)
@strategy_router.message(Command("strategy"), F.chat.id.in_(whitelist.chatIDs)) @strategyRouter.message(Command("strategy"), F.chat.id.in_(whitelist.chatIDs))
async def commandStrategy(message: Message, state: FSMContext): async def commandStrategy(message: Message, state: FSMContext):
await message.answer(strings.strategyCommand + '\n' + strings.askPair) await message.answer(strings.strategyCommand + '\n' + strings.askPair)
await state.set_state(startForm.pair) await state.set_state(startForm.pair)
@strategy_router.message(F.text, startForm.pair) @strategyRouter.message(F.text, startForm.pair)
async def capture_start_pair(message: Message, state: FSMContext): async def captureStartPair(message: Message, state: FSMContext):
await state.update_data(pair=message.text) await state.update_data(pair=message.text)
data = await state.get_data() data = await state.get_data()
@ -109,14 +110,14 @@ async def capture_start_pair(message: Message, state: FSMContext):
else: else:
await state.set_state(startForm.params) await state.set_state(startForm.params)
@strategy_router.message(F.text, startForm.params) @strategyRouter.message(F.text, startForm.params)
async def capture_params(message: Message, state: FSMContext): async def captureParams(message: Message, state: FSMContext):
await state.update_data(params=message.text) await state.update_data(params=message.text)
data = await state.get_data() data = await state.get_data()
t = await jsonProcessing.savePairParams(pair=data.get("pair"), params=data.get("params")) t = await jsonProcessing.savePairParams(pair=data.get("pair"), params=data.get("params"))
params = await jsonProcessing.parseParams(params=data.get("params"))
if t == 0: if t == 0:
params = await jsonProcessing.parseParams(params=data.get("params"))
client = await bybit.getClient( client = await bybit.getClient(
credentials.api_key, credentials.api_key,
credentials.api_secret, credentials.api_secret,
@ -160,13 +161,13 @@ async def capture_params(message: Message, state: FSMContext):
await state.clear() await state.clear()
@stop_router.message(Command("stop"), F.chat.id.in_(whitelist.chatIDs)) @stopRouter.message(Command("stop"), F.chat.id.in_(whitelist.chatIDs))
async def commandStop(message: Message, state: FSMContext): async def commandStop(message: Message, state: FSMContext):
await message.answer(strings.stopCommand + '\n' + strings.askPair) await message.answer(strings.stopCommand + '\n' + strings.askPair)
await state.set_state(stopForm.pair) await state.set_state(stopForm.pair)
@stop_router.message(F.text, stopForm.pair) @stopRouter.message(F.text, stopForm.pair)
async def capture_stop_pair(message: Message, state: FSMContext): async def captureStopPair(message: Message, state: FSMContext):
await state.update_data(pair=message.text) await state.update_data(pair=message.text)
data = await state.get_data() data = await state.get_data()
@ -180,13 +181,26 @@ async def capture_stop_pair(message: Message, state: FSMContext):
await state.clear() await state.clear()
async def start_bot(): async def startBot():
await set_commands() await setCommands()
try:
for i in whitelist.chatIDs:
await bot.send_message(chat_id=i, text=strings.startBot)
except Exception as e:
generalLogger.error(e)
async def stopBot():
try:
for i in whitelist.chatIDs:
await bot.send_message(chat_id=i, text=strings.stopBot)
except Exception as e:
generalLogger.error(e)
async def main() -> None: async def main() -> None:
dp.include_router(strategy_router) dp.include_router(strategyRouter)
dp.include_router(stop_router) dp.include_router(stopRouter)
dp.startup.register(start_bot) dp.startup.register(startBot)
dp.shutdown.register(stopBot)
await dp.start_polling(bot) await dp.start_polling(bot)