Skip to content

Commit

Permalink
Improve TraderoBot UI/UX
Browse files Browse the repository at this point in the history
- Make jump action accessible through UI
  • Loading branch information
math-a3k committed Aug 21, 2023
1 parent 2fdf3b7 commit 4211b28
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 10 deletions.
6 changes: 6 additions & 0 deletions base/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,9 @@ class Meta:
"api_key",
"api_secret",
]


class JumpingForm(forms.Form):
to_symbol = forms.ModelChoiceField(
queryset=Symbol.objects.available(), empty_label="(Selecionar)"
)
11 changes: 11 additions & 0 deletions base/templates/base/_jumping_form.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{% load bootstrap5 %}

<form method="post" action="{% url view obj.pk "jump" %}" class="row">
{% csrf_token %}
<div class="col-12">
<button type="submit" class="btn btn-primary">JUMP: </button>
</div>
<div class="col-3">
{% bootstrap_field form_jumping.to_symbol show_label=False wrapper_class="col-s12" %}
</div>
</form>
5 changes: 5 additions & 0 deletions base/templates/base/botzinhos_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ <h4>Actions</h4>
{% action_button action_url "Force SELL" "btn-danger" %}
{% endif %}
</li>
{% if not bot.price_buying %}
<li>
{% include "base/_jumping_form.html" with view="base:botzinhos-action" obj=bot %}
</li>
{% endif %}
<li>
{% if bot.status > bot.Status.INACTIVE %}
{% url "base:botzinhos-action" bot.pk "off" as action_url %}
Expand Down
31 changes: 31 additions & 0 deletions base/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,37 @@ def test_botzinhos_actions(self):
)
response = self.client.post(url, follow=True)
self.assertEqual(response.status_code, 200)
with requests_mock.Mocker() as m:
m.get(
f"{BINANCE_API_URL}/api/v3/ticker/price",
json={"symbol": "S1BUSD", "price": "1.0"},
)
url = reverse(
"base:botzinhos-action",
kwargs={
"pk": self.bot1.pk,
"action": "jump",
},
)
response = self.client.post(
url, {"to_symbol": self.s1.pk}, follow=True
)
self.assertEqual(response.status_code, 200)
self.assertIn(b"SUCCESS at", response.content)
with mock.patch(
"base.views.BotzinhosActionView.ACTIONS",
{"on": {"params": {"test_param": {"type": "test"}}}},
):
url = reverse(
"base:botzinhos-action",
kwargs={
"pk": self.bot1.pk,
"action": "on",
},
)
response = self.client.post(url, follow=True)
self.assertEqual(response.status_code, 200)
self.assertIn(b"SUCCESS at", response.content)
with mock.patch("base.models.TraderoBot.on") as bot_on_mock:
bot_on_mock.side_effect = Exception("New Exception")
url = reverse(
Expand Down
55 changes: 45 additions & 10 deletions base/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
)

from .forms import (
JumpingForm,
TraderoBotForm,
TraderoBotGroupEditForm,
TraderoBotGroupForm,
Expand Down Expand Up @@ -122,6 +123,7 @@ def get_context_data(self, **kwargs):
context["page_obj"] = page_obj
context["time_interval"] = settings.TIME_INTERVAL_BOTS
context["summary"] = summary
context["form_jumping"] = JumpingForm()
return context


Expand Down Expand Up @@ -171,14 +173,17 @@ class ActionView(OwnerMixin, LoginRequiredMixin, RedirectView):
def get_object(self):
raise NotImplementedError

def run_action(self, action):
def run_action(self):
try:
action_method = getattr(self.object, action)
action_method()
action_method = getattr(self.object, self.action)
if self.action_params:
action_method(**self.action_params)
else:
action_method()
messages.success(
self.request,
f"SUCCESS at {action.upper()} for {self.object.pk}:"
f"{self.object.name}",
f"SUCCESS at {self.action.upper()}({self.get_params_str()}) "
f"for [{self.object.pk}] {self.object.name}",
)
except Exception as e:
msg = e.args[0]
Expand All @@ -187,26 +192,56 @@ def run_action(self, action):
modname = mod.__name__ if mod else frm[1]
messages.error(
self.request,
f"ERROR at {action.upper()} for {self.object.pk}:"
f"{self.object.name}",
f"ERROR at {self.action.upper()}({self.get_params_str()}) "
f"for [{self.object.pk}] {self.object.name}: "
f"[{modname}] {str(msg)}",
)

def get_redirect_url(self, *args, **kwargs):
if kwargs["action"] not in self.ACTIONS:
self.action = kwargs["action"]
if self.action not in self.ACTIONS:
raise Http404("Action not Found")
self.action_params = self.process_params(self.request.POST)
self.pk = kwargs["pk"]
self.get_object()
self.run_action(kwargs["action"])
self.run_action()
return self.request.META.get("HTTP_REFERER", "/")

def get_params_str(self):
if self.action_params:
return ",".join(
[f"{k}={v}" for k, v in self.action_params.items()]
)
return ""

def process_params(self, data):
data = {k: v for k, v in data.items() if k != "csrfmiddlewaretoken"}
action_params = {}
action_params_conf = self.ACTIONS[self.action]["params"]
if action_params_conf:
for param in action_params_conf:
if action_params_conf[param]["type"] == "Model":
action_params[param] = get_object_or_404(
action_params_conf[param]["class"],
pk=data[param],
)
# Ignore non-compliant parameters
return action_params


class BotzinhosActionView(ActionView):
"""
Runs Actions on Botzinhos
"""

ACTIONS = ["buy", "sell", "on", "off", "reset"]
ACTIONS = {
"buy": {"params": None},
"sell": {"params": None},
"on": {"params": None},
"off": {"params": None},
"reset": {"params": None},
"jump": {"params": {"to_symbol": {"type": "Model", "class": Symbol}}},
}

def get_object(self):
self.object = get_object_or_404(TraderoBot, pk=self.pk)
Expand Down

0 comments on commit 4211b28

Please sign in to comment.