Version 04 als eigenes Repository
Erster Commit des Strangs "Optimierte Entscheidungsfindung mit Python" (Version 04). Die Historie der 71 Commits bis zur Trennung bleibt im uebergeordneten Repository OR_mit_Python liegen, das ab jetzt nur noch Version_03 (eingefroren) verwaltet und Version_04/ ignoriert. Bewusst kein "git subtree split": Der Pfad Version_04/ existiert erst seit der Verzeichnistrennung, ein Split braechte daher nur 7 der 41 einschlaegigen Commits - eine Teilhistorie, die vollstaendig aussieht und es nicht ist. Stand: 5 Teile, 23 Kapitel, 5 Anhaenge, 292 Abschnitte, 703 Querverweise, 325 Indexmarken, 73 Beispielprogramme, 32 SVGs, 4 Plotly-Figuren, 25 Notebooks, PDF mit 715 Seiten. Zusaetzlich in diesem Commit: * pyproject.toml mit Abhaengigkeitsgruppen finance, large-scale, api, figures, dev, empfehlungen. Die abgedruckte requirements.txt bleibt unveraendert daneben bestehen. ortools steht in der Grundausstattung, highspy erst in [large-scale] - so kann der HiGHS-Symbolkonflikt bei der schlanken Installation gar nicht erst auftreten. * Dabei zwei Funde: graphviz wird von erzeuge_architektur_diagramme.py importiert, fehlt aber in requirements.txt (jetzt in [figures]); pymoo steht in requirements.txt, wird aber von keinem Programm importiert, sondern nur im Kapitel Metaheuristiken empfohlen (jetzt in [empfehlungen]). * NEUER_TITEL.md nach Kritik_und_Verbesserungsvorschlaege/ verschoben - es ist die Vorlage des Titelblatts, kein Bestandteil des Werks. Die beiden Fundstellen in PROGRESS.md und erzeuge_titelseite.py nachgezogen. * PROGRESS.md nannte noch den Untertitel der ersten Fassung; auf den tatsaechlichen aus erzeuge_titelseite.py korrigiert. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
commit
b7af2f1d9a
468 changed files with 262141 additions and 0 deletions
96
OR_HTML_04/programme/Bot_Allokation.py
Normal file
96
OR_HTML_04/programme/Bot_Allokation.py
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Bot_Allokation.py
|
||||
"""
|
||||
Kapitel Einfuehrung: Erstes Optimierungsmodell mit Google OR-Tools (CP-SAT).
|
||||
Problem: Server-Allokation für Trading-Bots.
|
||||
|
||||
Modell mit expliziter Nebenbedingung statt versteckter Variablengrenze,
|
||||
vollständiger Statusauswertung und Ergebnisprüfung.
|
||||
"""
|
||||
|
||||
from ortools.sat.python import cp_model
|
||||
|
||||
# --- Parameter (die "Fakten" des Problems) ---------------------------------
|
||||
GEWINN_A, GEWINN_B = 150, 250 # Euro pro Bot und Tag
|
||||
CPU_A, CPU_B = 2, 5 # vCPU-Bedarf je Bot
|
||||
RAM_A, RAM_B = 4, 6 # GB Arbeitsspeicher je Bot
|
||||
CPU_GESAMT, RAM_GESAMT = 40, 60 # verfügbare Kapazitäten
|
||||
MAX_ARBITRAGE = 8 # Marktliquiditätsgrenze
|
||||
|
||||
|
||||
def loese_bot_allokation(zeitlimit_s: float = 10.0):
|
||||
"""Baut das Modell, löst es und gibt eine Auswertung aus."""
|
||||
|
||||
# 1. Modell instanziieren
|
||||
modell = cp_model.CpModel()
|
||||
|
||||
# 2. Entscheidungsvariablen anlegen
|
||||
# NewIntVar(untere_grenze, obere_grenze, name)
|
||||
# Die obere Grenze ist bewusst großzügig; die echte Beschränkung
|
||||
# formulieren wir unten als Nebenbedingung, damit das Modell die
|
||||
# mathematische Formulierung 1:1 abbildet.
|
||||
x_a = modell.NewIntVar(0, 100, "Arbitrage_Bots")
|
||||
x_b = modell.NewIntVar(0, 100, "Trend_Bots")
|
||||
|
||||
# 3. Nebenbedingungen definieren
|
||||
c_cpu = modell.Add(CPU_A * x_a + CPU_B * x_b <= CPU_GESAMT) # vCPU-Limit
|
||||
c_ram = modell.Add(RAM_A * x_a + RAM_B * x_b <= RAM_GESAMT) # RAM-Limit
|
||||
c_liq = modell.Add(x_a <= MAX_ARBITRAGE) # Marktliquidität
|
||||
|
||||
# 4. Zielfunktion: Maximiere den Tagesgewinn
|
||||
modell.Maximize(GEWINN_A * x_a + GEWINN_B * x_b)
|
||||
|
||||
# 5. Solver konfigurieren und ausführen
|
||||
loeser = cp_model.CpSolver()
|
||||
loeser.parameters.max_time_in_seconds = zeitlimit_s
|
||||
status = loeser.Solve(modell)
|
||||
|
||||
# 6. Status auswerten -- IMMER alle Fälle behandeln
|
||||
status_text = loeser.StatusName(status)
|
||||
if status not in (cp_model.OPTIMAL, cp_model.FEASIBLE):
|
||||
print(f"Keine verwertbare Lösung. Solver-Status: {status_text}")
|
||||
if status == cp_model.INFEASIBLE:
|
||||
print("Das Modell ist unlösbar - die Bedingungen widersprechen sich.")
|
||||
return None
|
||||
|
||||
a, b = loeser.Value(x_a), loeser.Value(x_b)
|
||||
gewinn = loeser.ObjectiveValue()
|
||||
|
||||
# 7. Ergebnis ausgeben
|
||||
print("=" * 58)
|
||||
print(" OPTIMALE BOT-ALLOKATION")
|
||||
print("=" * 58)
|
||||
print(f"Solver-Status: {status_text}"
|
||||
f"{' (beweisbar optimal)' if status == cp_model.OPTIMAL else ' (zulässig, nicht bewiesen)'}")
|
||||
print(f"Arbitrage-Bots (x_A): {a} Instanzen")
|
||||
print(f"Trendfolge-Bots (x_B): {b} Instanzen")
|
||||
print(f"Täglicher Max-Gewinn: {gewinn:,.2f} EUR")
|
||||
|
||||
genutzt_cpu = CPU_A * a + CPU_B * b
|
||||
genutzt_ram = RAM_A * a + RAM_B * b
|
||||
print("-" * 58)
|
||||
print(f"CPU-Auslastung: {genutzt_cpu} / {CPU_GESAMT} vCPUs "
|
||||
f"({genutzt_cpu / CPU_GESAMT * 100:.1f} %)")
|
||||
print(f"RAM-Auslastung: {genutzt_ram} / {RAM_GESAMT} GB "
|
||||
f"({genutzt_ram / RAM_GESAMT * 100:.1f} %)")
|
||||
print(f"Arbitrage-Limit: {a} / {MAX_ARBITRAGE}")
|
||||
|
||||
# 8. Selbstkontrolle: Sind wirklich alle Bedingungen eingehalten?
|
||||
assert genutzt_cpu <= CPU_GESAMT, "vCPU-Limit verletzt!"
|
||||
assert genutzt_ram <= RAM_GESAMT, "RAM-Limit verletzt!"
|
||||
assert a <= MAX_ARBITRAGE, "Arbitrage-Limit verletzt!"
|
||||
|
||||
# 9. Zum Vergleich: die naive Strategie "nur der lukrativere Bot"
|
||||
naiv_b = min(CPU_GESAMT // CPU_B, RAM_GESAMT // RAM_B)
|
||||
naiv_gewinn = GEWINN_B * naiv_b
|
||||
print("-" * 58)
|
||||
print(f"Naive Strategie (nur Trendfolge): {naiv_b} Bots -> {naiv_gewinn:,.2f} EUR")
|
||||
print(f"Vorteil der Optimierung: {gewinn - naiv_gewinn:,.2f} EUR pro Tag "
|
||||
f"({(gewinn / naiv_gewinn - 1) * 100:.1f} %)")
|
||||
print("=" * 58)
|
||||
return a, b, gewinn
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
loese_bot_allokation()
|
||||
Loading…
Reference in a new issue