Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wiseplat
GitHub Repository: wiseplat/python-code
Path: blob/master/ invest-robot-contest_invest-bot-main/blog/blogger.py
5925 views
1
import asyncio
2
import logging
3
from decimal import Decimal
4
5
from tinkoff.invest import OrderState
6
7
from configuration.settings import BlogSettings, StrategySettings
8
from invest_api.utils import moneyvalue_to_decimal
9
from trade_system.signal import SignalType
10
from trade_system.strategies.base_strategy import IStrategy
11
from trading.trade_results import TradeOrder
12
13
__all__ = ("Blogger")
14
15
logger = logging.getLogger(__name__)
16
17
18
class Blogger:
19
"""
20
Class formats and sends messages to telegram chat.
21
"""
22
def __init__(
23
self,
24
blog_settings: BlogSettings,
25
trade_strategies: list[StrategySettings],
26
messages_queue: asyncio.Queue
27
) -> None:
28
self.__blog_status = blog_settings.blog_status
29
self.__trade_strategies: dict[str, StrategySettings] = {x.figi: x for x in trade_strategies}
30
self.__messages_queue = messages_queue
31
32
def __send_text_message(self, text: str) -> None:
33
try:
34
logger.debug(f"Put message to telegram messages queue: {text}")
35
36
self.__messages_queue.put_nowait(text)
37
except Exception as ex:
38
logger.error(f"Error put message to telegram messages queue: {repr(ex)}")
39
40
def start_trading_message(
41
self,
42
today_trade_strategy: dict[str, IStrategy],
43
rub_before_trade_day: Decimal
44
) -> None:
45
"""
46
The method sends message about depo size, list of stocks for today trading and greetings also.
47
"""
48
if self.__blog_status:
49
self.__send_text_message("Greetings! We are starting.")
50
self.__send_text_message(f"Depo size: {rub_before_trade_day:.2f} rub")
51
self.__send_text_message("Stocks list:")
52
for figi_key, strategy_value in today_trade_strategy.items():
53
self.__send_text_message(
54
f"Ticker: {strategy_value.settings.ticker}. "
55
f"Short trade status: {strategy_value.settings.short_enabled_flag}"
56
)
57
58
def finish_trading_message(self) -> None:
59
"""
60
The method sends information that trading is stopping.
61
"""
62
if self.__blog_status:
63
self.__send_text_message("We are closing trading day.")
64
65
def close_position_message(self, trade_order: TradeOrder) -> None:
66
"""
67
The method sends information about closed position.
68
"""
69
if self.__blog_status and trade_order:
70
signal_type = Blogger.__signal_type_to_message_test(trade_order.signal.signal_type)
71
self.__send_text_message(
72
f"{self.__trade_strategies[trade_order.signal.figi].ticker} position {signal_type} has been closed."
73
)
74
75
def open_position_message(self, trade_order: TradeOrder) -> None:
76
"""
77
The method sends information about opened position.
78
"""
79
if self.__blog_status and trade_order:
80
signal_type = Blogger.__signal_type_to_message_test(trade_order.signal.signal_type)
81
self.__send_text_message(
82
f"{self.__trade_strategies[trade_order.signal.figi].ticker} position {signal_type} has been opened. "
83
f"Take profit level: {trade_order.signal.take_profit_level:.2f}. "
84
f"Stop loss level: {trade_order.signal.stop_loss_level:.2f}."
85
)
86
87
def trading_depo_summary_message(
88
self,
89
rub_before_trade_day: Decimal,
90
current_rub_on_depo: Decimal
91
) -> None:
92
"""
93
The method sends information about trading day summary.
94
"""
95
if self.__blog_status:
96
self.__send_text_message(
97
f"Start depo: {rub_before_trade_day:.2f} close depo:{current_rub_on_depo:.2f}."
98
)
99
100
today_profit = current_rub_on_depo - rub_before_trade_day
101
today_percent_profit = (today_profit / rub_before_trade_day) * 100
102
self.__send_text_message(f"Today leverage: {today_profit:.2f} rub ({today_percent_profit:.2f} %)")
103
104
def fail_message(self):
105
"""
106
The method sends information about emergency situation in bot.
107
"""
108
if self.__blog_status:
109
self.__send_text_message(
110
f"Something went wrong. We are trying to close all positions. "
111
f"If we fail, please try to do it himself."
112
)
113
114
def summary_message(self):
115
"""
116
The method sends just summary title.
117
"""
118
if self.__blog_status:
119
self.__send_text_message(f"Trading day summary:")
120
121
def final_message(self):
122
"""
123
The method sends just goodbye title.
124
"""
125
if self.__blog_status:
126
self.__send_text_message(f"Trading has been completed. See you on next trade day!")
127
128
def summary_open_signal_message(self, trade_order: TradeOrder, open_order_state: OrderState):
129
"""
130
The method sends summary information about only open positions (not closed)
131
"""
132
if self.__blog_status:
133
signal_type = Blogger.__signal_type_to_message_test(trade_order.signal.signal_type)
134
summary_commission = moneyvalue_to_decimal(open_order_state.executed_commission) + \
135
moneyvalue_to_decimal(open_order_state.service_commission)
136
self.__send_text_message(
137
f"Open {signal_type} position for {self.__trade_strategies[trade_order.signal.figi].ticker}. "
138
f"Lots executed: {open_order_state.lots_executed}. "
139
f"Average price: "
140
f"{moneyvalue_to_decimal(open_order_state.average_position_price):.2f}. "
141
f"Total order price: "
142
f"{moneyvalue_to_decimal(open_order_state.total_order_amount):.2f}. "
143
f"Total commissions: "
144
f"{summary_commission:.2f}. "
145
f"You have to close position manually."
146
)
147
148
def summary_closed_signal_message(self,
149
trade_order: TradeOrder,
150
open_order_state: OrderState,
151
close_order_state: OrderState
152
) -> None:
153
"""
154
The method sends summary information about closed positions
155
"""
156
if self.__blog_status:
157
signal_type = Blogger.__signal_type_to_message_test(trade_order.signal.signal_type)
158
summary_commission = moneyvalue_to_decimal(open_order_state.executed_commission) + \
159
moneyvalue_to_decimal(open_order_state.service_commission) + \
160
moneyvalue_to_decimal(close_order_state.executed_commission) + \
161
moneyvalue_to_decimal(close_order_state.service_commission)
162
self.__send_text_message(
163
f"Close {signal_type} position for {self.__trade_strategies[trade_order.signal.figi].ticker}. "
164
f"Lots executed: {close_order_state.lots_executed}. "
165
f"Average open price: "
166
f"{moneyvalue_to_decimal(open_order_state.average_position_price):.2f}. "
167
f"Average close price: "
168
f"{moneyvalue_to_decimal(close_order_state.average_position_price):.2f}. "
169
f"Summary: "
170
f"{moneyvalue_to_decimal(close_order_state.total_order_amount) - moneyvalue_to_decimal(open_order_state.total_order_amount):.2f}. "
171
f"Total commissions: "
172
f"{summary_commission:.2f}."
173
)
174
175
@staticmethod
176
def __signal_type_to_message_test(signal_type: SignalType) -> str:
177
return "long" if signal_type == SignalType.LONG else "short"
178
179