Skip to content
This repository was archived by the owner on Jun 16, 2024. It is now read-only.

Commit d95f6c9

Browse files
author
0x78f1935
committed
Minor updates
1 parent ffd9020 commit d95f6c9

File tree

18 files changed

+289
-338
lines changed

18 files changed

+289
-338
lines changed

backend/config/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class Config(System):
1111
"""
1212
def __init__(self) -> None:
1313
self.DEBUG = False
14-
self.VERSION = "1.0.2"
14+
self.VERSION = "1.1.0"
1515
self.PROJECT_NAME = "PyNance - Webinterface"
1616

1717
# Load system configuration

backend/models/system.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,14 @@ class SystemModel(db.Model):
2323
Indicates the second currency of the symbol
2424
take_profit: string
2525
The proft taken from the trading
26+
total_entry: string
27+
The total amount of % used in the selected wallet to buy with
2628
online: boolean
2729
indicates if the bot is trading
30+
buying: boolean
31+
indicates if the bot is buying or not
32+
panik: boolean
33+
indicates if the bot is in panik mode
2834
"""
2935

3036
__tablename__ = "system"
@@ -35,11 +41,14 @@ class SystemModel(db.Model):
3541
currency_2 = db.Column(db.Text, default="USDT")
3642

3743
take_profit = db.Column(db.Text, default="20")
44+
total_entry = db.Column(db.Text, default="100")
3845
only_dip = db.Column(db.Boolean, default=True)
3946
online = db.Column(db.Boolean, default=False, onupdate=False)
40-
47+
buying = db.Column(db.Boolean, default=True)
4148
panik = db.Column(db.Boolean, default=False)
4249

50+
current_value = db.Column(db.Text, default="0")
51+
4352
def update_data(self, data: dict):
4453
""""Just throw in a json object, each key that can be mapped will be updated"
4554

backend/views/api/configure.py

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,14 @@ class ConfigureApiView(FlaskView):
1313

1414
decorators = [ ]
1515

16-
@route('/take_profit', methods=['GET'])
16+
@route('/take_profit', methods=['POST', 'GET'])
1717
def take_profit(self):
1818
model = SystemModel.query.first()
19-
return jsonify({'take_profit': int(model.take_profit)}), 200
20-
21-
@route('/take_profit', methods=['POST'])
22-
def set_take_profit(self):
23-
model = SystemModel.query.first()
24-
if model.take_profit != str(request.json['tp']):
25-
model.take_profit = str(request.json['tp'])
26-
db.session.add(model)
27-
db.session.commit()
19+
if request.method == 'POST':
20+
if model.take_profit != str(request.json['tp']):
21+
model.take_profit = str(request.json['tp'])
22+
db.session.add(model)
23+
db.session.commit()
2824
return jsonify({'take_profit': int(model.take_profit)}), 200
2925

3026
@route('/online', methods=['GET'])
@@ -64,8 +60,23 @@ def panik(self):
6460
else:
6561
return jsonify({'panik': model.panik}), 200
6662

67-
@route('/only_dip', methods=['POST'])
63+
@route('/only_dip', methods=['POST', 'GET'])
6864
def only_dip(self):
6965
model = SystemModel.query.first()
70-
model.update_data({'only_dip': not request.json['dip']})
66+
if request.method == 'POST':
67+
online = model.online # Prevents model to set itself to false
68+
model.update_data({'only_dip': not request.json['dip']})
69+
model.online = online
70+
db.session.add(model)
71+
db.session.commit()
7172
return jsonify({'dip': model.only_dip}), 200
73+
74+
@route('/total_entry', methods=['POST', 'GET'])
75+
def set_take_profit(self):
76+
model = SystemModel.query.first()
77+
if request.method == 'POST':
78+
if model.total_entry != str(request.json['total_entry']):
79+
model.total_entry = str(request.json['total_entry'])
80+
db.session.add(model)
81+
db.session.commit()
82+
return jsonify({'total_entry': int(model.total_entry)}), 200

backend/views/api/orders.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ def get(self):
2020
for item in data:
2121
order_item = {}
2222
order_item["Symbol"] = item["symbol"]
23+
order_item["Created"] = item["created"]
24+
order_item["Updated"] = item["updated"]
2325
order_item["Active"] = str(bool(item["current"])).capitalize() if str(model.currency_1 + model.currency_2) in order_item["Symbol"] else "False"
2426
order_item["quantity"] = float(item["quantity"])
2527
order_item["paid_total"] = float(item["brought_price"]) * order_item["quantity"]

backend/views/api/system.py

Lines changed: 118 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ class SystemApiView(FlaskView):
1919

2020
def get_x_percentage_of_y(self, x, y): return float(y / 100) * x
2121

22+
def update_system_without_going_offline(self, system, data):
23+
online = system.online
24+
system.update_data(data)
25+
system.online = online
26+
db.session.add(system)
27+
db.session.commit()
28+
return system
29+
2230
def get(self):
2331
now = datetime.now()
2432

@@ -46,9 +54,6 @@ def get(self):
4654
try:
4755
price_average = float(pynance.price.average(cur1+cur2).json["price"])
4856
except AttributeError:
49-
# system.online = False
50-
# db.session.add(system)
51-
# db.session.commit()
5257
chatterer.chat("UNKNOWN SYMBOL")
5358
return jsonify({
5459
"date": str(datetime.now().strftime('%d-%m-%y %H:%M:%S')),
@@ -57,17 +62,16 @@ def get(self):
5762
"msg": chatterer.msg
5863
}), 200
5964

60-
if model is None: brought_price = price_average
61-
else: brought_price = float(model.brought_price)
62-
63-
take_profit = float(system.take_profit) # The percentage to take as profit, cannot be higher then 99
65+
# The work price is or the average price, or the price which we brought for
66+
if model is None: work_price = price_average
67+
else: work_price = float(model.brought_price)
68+
# The percentage to take as profit, cannot be higher then 99
69+
take_profit = float(system.take_profit)
6470

6571
try:
72+
# Check if we can get the fees, which also allows us to check if Binance is available
6673
fees = pynance.price.fees(cur1+cur2).json['tradeFee'].pop(0)
6774
except AttributeError:
68-
# system.online = False
69-
# db.session.add(system)
70-
# db.session.commit()
7175
chatterer.chat("BINANCE SERVICES ARE UNAVAILABLE AT THIS TIME")
7276
return jsonify({
7377
"date": str(datetime.now().strftime('%d-%m-%y %H:%M:%S')),
@@ -76,99 +80,118 @@ def get(self):
7680
"msg": chatterer.msg
7781
}), 200
7882

79-
fee_maker = 1 + fees['maker'] * 100 # Maker -> Buys crypto
80-
fee_taker = 1 + fees['taker'] * 100 # Taker -> Sells crypto
83+
# Get the fees from the response
84+
fee_maker = fees['maker'] # Maker -> Buys crypto
85+
fee_taker = fees['taker'] # Taker -> Sells crypto
8186
symbol = fees['symbol']
8287

88+
# Get information about the selected symbol
8389
exchange_info = pynance.exchange_info(symbol)
8490
stepSize = [ i for i in exchange_info['filters'] if i['filterType'] == 'LOT_SIZE'].pop(0)['stepSize']
8591
precision = int(round(-math.log(float(stepSize), 10), 0))
8692

87-
balance = pynance.wallet.balance(cur1)
88-
balance2 = pynance.wallet.balance(cur2)
89-
90-
balance_free = float(balance['free']) # BTC
91-
balance_locked = float(balance['locked'])
92-
balance2_free = float(balance2['free']) # USDT
93-
balance2_locked = float(balance2['locked'])
94-
current_price = float(pynance.price.asset(cur1+cur2).json['price'])
95-
96-
# Price of the fees we paid
97-
paid_fees = float(brought_price * balance_free) * float(fee_taker/100)
98-
# Price including fees we have paid
99-
paid_total = float(brought_price * balance_free) + paid_fees
100-
101-
# Price of the fees if we wouldve brought
102-
wouldve_paid_fees = float(current_price * balance_free) * float(fee_taker/100)
103-
# Total price including fees if we brought
104-
wouldve_paid = float(current_price * balance_free) + wouldve_paid_fees
105-
106-
if model is not None:
107-
chatterer.update_price(f"{float(round(float(current_price) * float(model.quantity), 6))} - { float(round(current_price, 6)) } - { model.quantity }")
108-
else: chatterer.update_price(f"0.0 - { float(round(current_price, 6)) } - 0")
109-
110-
wanted_profit = paid_total * float(take_profit/100)
111-
sellprice_without_loss_on_fee_plus_profit = float(round(float(paid_total + wanted_profit), precision))
112-
113-
minimal_money_needed_to_buy = current_price*0.1 #
114-
115-
# If we are in profit or if the bot is panikkin + the price is higher then what we paid; we sell.
116-
if wouldve_paid > sellprice_without_loss_on_fee_plus_profit or system.panik and wouldve_paid > paid_total:
117-
chatterer.chat(f"SELLING {cur1}")
118-
quantity = float(round(self.get_x_percentage_of_y(99.9, balance_free), precision))
119-
sell_order = pynance.orders.create(symbol, quantity, False, order_id='test_api')
120-
if sell_order is not None:
121-
data = sell_order.json['fills'].pop(0)
122-
# Price of the fees we paid
123-
paid_fees = float(float(data['price']) * balance_free) * float(fee_taker/100)
124-
# Price including fees we have paid
125-
paid_total = float(float(data['price']) * balance_free) + paid_fees
126-
wanted_profit = paid_total * float(take_profit/100)
127-
sellprice_without_loss_on_fee_plus_profit = float(round(float(paid_total + wanted_profit), precision))
128-
129-
if model is not None:
130-
model.update_data({
131-
'current': False,
132-
'sold_for': str(wouldve_paid)
133-
})
134-
chatterer.chat(f"SOLD {cur1}: {quantity}")
135-
else: chatterer.chat("NOTHING TO SELL")
136-
else:
93+
# Check for each currency selected what we have available in the wallet
94+
balance = pynance.wallet.balance(cur1) # BTC
95+
balance2 = pynance.wallet.balance(cur2) # USDT
96+
97+
# Each wallet has free amounts and locked amounts, locked is not usable.
98+
balance_free = float(round(float(balance['free']), 8)) # BTC
99+
balance_locked = float(round(float(balance['locked']), 8))
100+
balance2_free = float(round(float(balance2['free']), 8)) # USDT
101+
balance2_locked = float(round(float(balance2['locked']), 8))
102+
current_price = float(round(float(pynance.price.asset(cur1+cur2).json['price']), 8))
103+
# Register the current value
104+
system = self.update_system_without_going_offline(system, {'current_value': str(current_price)})
105+
106+
expected_profit = float(round(float(float(work_price / 100) * take_profit), 8))
107+
total_profit_on_each_coin = float(round(float(work_price + expected_profit), 8)) # * quantity == sell_target
108+
109+
# Debug stuff
110+
# print(f"The work price is: {work_price}")
111+
# print(f"Take profit: {take_profit}%")
112+
# print(f"Fees limit sell / buy: {fee_maker}")
113+
# print(f"Fees market sell / buy: {fee_taker}")
114+
# print(f"Balance {cur1} -> free {balance_free}, locked {balance_locked}")
115+
# print(f"Balance2 {cur2} -> free {balance2_free}, locked {balance2_locked}")
116+
# print(f"Current price {current_price}")
117+
# print(f"Expected profit: {expected_profit}")
118+
# print(f"Buying? : {system.buying}")
119+
120+
if system.buying:
121+
fees_current_price = float(round(float(float(work_price) * fee_taker), 8))
122+
price_including_fee = float(round(float(float(balance_free)), 8))
123+
price_excluding_fee = float(round(float(float(balance_free - fees_current_price)), 8))
124+
137125
if model is None:
138-
if balance2_free > minimal_money_needed_to_buy:
139-
if system.panik:
140-
chatterer.chat("PANIK, NO NEW BUY ORDER WILL BE PLACED")
141-
else:
142-
# Check if the current price is below average
143-
if system.only_dip:
144-
price_average_would_buy = float(price_average - float(price_average * float(float(take_profit/100)/10)))
145-
else: price_average_would_buy = price_average
146-
if current_price < price_average_would_buy:
147-
chatterer.chat(f"BUYING {cur1}")
148-
quantity = float(f"{self.get_x_percentage_of_y(100-take_profit, balance2_free / current_price ):.{precision}f}")
149-
buy_order = pynance.orders.create(symbol, quantity, order_id='test_api')
150-
if buy_order is not None:
151-
data = buy_order.json['fills'].pop(0)
152-
brought_price = float(data['price'])
153-
model = OrdersModel(
154-
symbol=symbol,
155-
currency_1=cur1,
156-
currency_2=cur2,
157-
quantity=str(quantity),
158-
brought_price=str(brought_price),
159-
fee_maker=str(fee_maker),
160-
fee_taker=str(fee_taker),
161-
)
162-
db.session.add(model)
163-
db.session.commit()
164-
chatterer.chat(f"BROUGHT: {quantity}")
165-
else: chatterer.chat(f"CURRENT {cur1} PRICE ({current_price}) NOT BELOW AVERAGE ({price_average_would_buy}), SKIPPING BUY ORDERS")
166-
else: chatterer.chat("NOT ENOUGH MONEY TO BUY")
167-
else:
168-
if system.panik:
169-
chatterer.chat(f"HOLDING {cur1} STRONG, CURRENT PRICE ({current_price}) TO LOW TO SELL, TARGET PRICE ({paid_total})")
126+
if system.panik: chatterer.chat("PANIK ACTIVE, NO NEW BUY ORDER WILL BE PLACED")
170127
else:
171-
chatterer.chat(f"HOLDING {cur1} STRONG, CURRENT PRICE ({current_price}) TO LOW TO SELL, TARGET PRICE ({sellprice_without_loss_on_fee_plus_profit})")
128+
if system.only_dip: price_entry = float(work_price - float(expected_profit))
129+
else: price_entry = float(work_price - float(expected_profit / 2))
130+
131+
if current_price <= price_entry:
132+
chatterer.chat(f"BUYING {cur1}")
133+
quantity = float(float(float(float(balance2_free / current_price) / 100) * float(system.total_entry)))
134+
buy_order = pynance.orders.create(symbol, float(round(float(quantity - float(quantity/100)), precision)), order_id='test_api')
135+
if buy_order is not None:
136+
data = buy_order.json['fills'].pop(0)
137+
brought_price = float(round(float(data['price']), 8))
138+
model = OrdersModel(
139+
symbol=symbol,
140+
currency_1=cur1,
141+
currency_2=cur2,
142+
quantity=str(quantity),
143+
brought_price=str(brought_price),
144+
fee_maker=str(fee_maker),
145+
fee_taker=str(fee_taker),
146+
)
147+
db.session.add(model)
148+
db.session.commit()
149+
chatterer.chat(f"BROUGHT {quantity} {cur1} FOR {brought_price} {cur2}")
150+
system = self.update_system_without_going_offline(system, {'buying': False}) # Reset state
151+
else: chatterer.chat(f"UNABLE TO PLACE A BUY ORDER FOR {quantity} {cur1}")
152+
else: chatterer.chat(f"CURRENT {cur1} PRICE ({current_price}) NOT AT BUY TARGET ({price_entry}), SKIPPING BUY ORDER")
153+
else:
154+
system = self.update_system_without_going_offline(system, {'buying': False}) # Reset state
155+
chatterer.chat("NOT ENOUGH MONEY TO PLACE A BUY ORDER")
156+
else:
157+
fees_current_price = float(round(float(float(work_price) * fee_taker), 8))
158+
price_including_fee = float(round(float(float(balance2_free)), 8))
159+
price_excluding_fee = float(round(float(float(balance2_free - fees_current_price)), 8))
160+
161+
if model is None:
162+
chatterer.chat("No coin available to sell, you seem to be out of stock!")
163+
system = self.update_system_without_going_offline(system, {'buying': True}) # Reset state
164+
return jsonify({
165+
"date": str(datetime.now().strftime('%d-%m-%y %H:%M:%S')),
166+
"execution_time": str(datetime.now()-now),
167+
"online": True,
168+
"msg": chatterer.msg
169+
}), 200
170+
171+
quantity = float(round(float(model.quantity), precision))
172+
sell_target = float(round(float(float(total_profit_on_each_coin * quantity) + float(float(total_profit_on_each_coin * quantity) * fee_taker)), 8))
173+
174+
previous_price_order = float(round(float(work_price * quantity), 8))
175+
expected_total_profit = float(round(float(sell_target - previous_price_order), 8))
176+
total_fomo_price = float(round(float(work_price + fees_current_price), 8))
177+
fomo_price = float(round(float(float(total_fomo_price * quantity) + float(float(total_fomo_price * quantity) * fee_taker)), 8))
178+
179+
if system.panik: chatterer.chat(f"{quantity} {cur1} IS {previous_price_order} {cur2} WORTH - TRYING TO SELL FOR {fomo_price} {cur2}")
180+
else: chatterer.chat(f"{quantity} {cur1} IS {previous_price_order} {cur2} WORTH - TRYING TO SELL FOR {sell_target} {cur2}")
181+
182+
if current_price > total_profit_on_each_coin or system.panik and current_price > total_fomo_price:
183+
chatterer.chat(f"SELLING {cur1}")
184+
sell_order = pynance.orders.create(symbol, float(round(float(quantity - float(quantity/100)), precision)), buy=False, order_id='test_api')
185+
if sell_order is not None:
186+
sold_price = float(round(float(current_price * quantity), 8))
187+
if model is not None:
188+
model.update_data({
189+
'current': False,
190+
'sold_for': str(sold_price)
191+
})
192+
chatterer.chat(f"SOLD {quantity} {cur1} FOR AN AMAZING {sold_price} {cur2}")
193+
system = self.update_system_without_going_offline(system, {'buying': True}) # Reset state
194+
else: chatterer.chat(f"UNABLE TO PLACE A SELL ORDER FOR {quantity} {cur1}")
172195

173196
return jsonify({
174197
"date": str(datetime.now().strftime('%d-%m-%y %H:%M:%S')),

backend/views/api/ui.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,10 @@ def current_price(self):
6666
fiat, coin, quantity = model.current_price.split(' - ')
6767
return jsonify({'fiat': fiat, 'coin': coin, 'quantity': quantity}), 200
6868
except ValueError: pass
69-
return jsonify({'fiat': 0, 'coin': 0, 'quantity': 0}), 200
69+
return jsonify({'fiat': 0, 'coin': 0, 'quantity': 0}), 200
70+
71+
@route('/v2/current_price', methods=['GET'])
72+
def current_price_2(self):
73+
model = SystemModel.query.first()
74+
return jsonify({'price': model.current_value}), 200
75+

0 commit comments

Comments
 (0)