Stapelbörse Börse - V3


42

HINWEIS: Diese Herausforderung ist jetzt geschlossen: Ich werde die Bestenliste nicht mehr aktualisieren und die akzeptierte Antwort nicht ändern. Es steht Ihnen jedoch frei, den Controller selbst auszuführen und die Bestenliste zu aktualisieren, wenn Sie dies wünschen.

Tritt dem Chat bei!

Einführung

Guten Abend, Händler! Sie sind alle Händler für das Golfunternehmen PPCG. Ihre Aufgabe ist es, so viel Geld wie möglich zu verdienen.

Herausforderung

Schreiben Sie ein Programm, das Aktien an der Stack Exchange Stock Exchange kauft und verkauft, um so viel Geld wie möglich zu verdienen.

Spielweise

Alle Spieler beginnen mit 5 Aktien und 100 $ auf ihrer Bank. Das Spiel beginnt immer mit einem Aktienkurs von 10 USD.

Jedes Spiel hat 1000 Runden, in denen die erste Runde ist 1. In jeder Runde erhält Ihr Programm vier Argumente als Eingabe: den aktuellen Aktienkurs, die Anzahl der von Ihnen gehaltenen Aktien, den Betrag, den Sie besitzen, und die Rundennummer (1-indexiert).

Zum Beispiel, wenn mein Programm ist test1.py, der Aktienkurs ist 100, die Anzahl der Aktien, die ich halte 3, der Geldbetrag, den ich habe 1200, und die runde Zahl ist 576, wird mein Programm wie folgt ausgeführt:

python test1.py 100 3 1200 576

In einer Runde ist der Aktienkurs, den jeder Spieler erhält, derselbe. Dies ändert sich erst am Ende der Runde.

Als Antwort muss der Spieler seinen Befehl ausdrucken. Es gibt zwei Möglichkeiten:

  • Kaufen Aktien: Dieser Befehl wird gegeben , wie , bnwo ndie Anzahl der Aktien , die Sie kaufen möchten. Wenn Sie beispielsweise 100 Aktien kaufen möchten, würden Sie Folgendes ausgeben:
b100

Beim Kauf von Anteilen ist eine Überziehung von bis zu 1000 USD zulässig. Wenn Sie versuchen, genügend Aktien zu kaufen, die diesen Überziehungsbetrag überschreiten (Ihr Kontostand liegt unter -1000 USD), werden Sie für bankrott erklärt. Dies bedeutet, dass Sie alle Ihre Anteile verlieren und Ihr Kontostand auf 50 USD festgelegt wird.

Der Aktienkurs bleibt von Ihrem Befehl unberührt, wenn Sie in Konkurs gehen.

(Wenn Ihr Guthaben -1000 US-Dollar beträgt, sind Sie nicht bankrott. Wenn Ihr Guthaben jedoch -1001 US-Dollar beträgt, sind Sie bankrott.)

  • Verkaufen Aktien: Dieser Befehl wie angegeben , snwo ndie Anzahl der Aktien , die Sie verkaufen möchten. Wenn Sie beispielsweise 100 Aktien verkaufen möchten, würden Sie Folgendes ausgeben:
s100

Sie dürfen nicht mehr Aktien verkaufen als Sie besitzen. Wenn Sie dies versuchen, wird Ihre Anfrage abgelehnt und Sie überspringen die Runde.

Wenn Sie die Runde überspringen und nichts tun möchten, geben Sie entweder b0oder aus s0.

Ihre Anfrage wird abgelehnt, wenn Sie versuchen, eine negative Anzahl von Aktien und / oder eine nicht ganzzahlige Anzahl von Aktien zu kaufen oder zu verkaufen.

Nach 5 Runden erhalten alle Spieler am Ende jeder Runde eine Dividende, deren Wert 5% des durchschnittlichen Aktienkurses der letzten 5 Runden beträgt.

Wie funktioniert es?

Zunächst wird der Aktienkurs 10 US-Dollar betragen. Am Ende jeder Runde wird es nach folgender Formel neu berechnet:

New Share Price=Old Share Price+(Number of shares boughtNumber of shares sold)

Der Aktienkurs wird begrenzt, so dass er niemals unter 1 USD fällt.

Um zu schnelle Änderungen zu vermeiden, ist die Änderung des Aktienkurses auf maximal .±$200

Regeln

  • Ihr Programm muss einen Namen haben


  • Ihrem Programm ist eine einzige Textdatei zur Datenspeicherung gestattet. Es muss im selben Ordner wie Ihr Programm gespeichert sein


  • Geben Sie in Ihrer Antwort an, wie Sie Ihr Programm ausführen


  • Diese KotH steht allen frei verwendbaren Programmiersprachen offen, die unter Windows 10 ausgeführt werden können


  • Ihre Punktzahl basiert ausschließlich auf dem Inhalt Ihres Guthabens. Etwaiges in Anteilen gebundenes Geld wird nicht gezählt


  • Sie können Ihr Programm jederzeit bearbeiten. Vor jedem Spiel wird der neueste Code gespeichert und kompiliert


  • Sie sollten keinen Code schreiben, der speziell auf einen anderen Bot abzielt.

Regler

Der Controller ist in Python geschrieben und hier zu finden: https://gist.github.com/beta-decay/a6abe40fc9f4ff6cac443395377ec31f

Am Ende wird eine Rangliste gedruckt und eine Grafik darüber angezeigt, wie sich der Aktienkurs im Laufe des Spiels verändert hat.

Zum Beispiel, wenn zwei zufällige Bots gespielt wurden

Gewinnen

Der Spieler mit dem höchsten Geldbetrag am Ende des letzten Spiels gewinnt.

Bestenliste

Spiel 4: 16:14 10/08/2018

Name                                Balance

Experienced Greedy Idiot            $14802860126910608746226775271608441476740220190868405578697473058787503167301288688412912141064764060957801420415934984247914753474481204843420999117641289792179203440895025689047561483400211597324662824868794009792985857917296068788434607950379253177065699908166901854516163240207641611196996217004494096517064741782361827125867827455285639964058498121173062045074772914323311612234964464095317202678432969866099864014974786854889944224928268964434751475446606732939913688961295787813863551384458839364617299883106342420461998689419913505735314365685264187374513996061826694192786379011458348988554845036604940421113739997490412464158065355335378462589602228039730
Equalizer                           $763185511031294813246284506179317396432985772155750823910419030867990447973211564091988995290789610193513321528772412563772470011147066425321453744308521967943712734185479563642323459564466177543928912648398244481744861744565800383179966018254551412512770699653538211331184147038781605464336206279313836606330
Percentage Trader                   $448397954167281544772103458977846133762031629256561243713673243996259286459758487106045850187688160858986472490834559645508673466589151486119551222357206708156491069820990603783876340193236064700332082781080188011584263709364962735827741094223755467455209136453381715027369221484319039100339776026752813930
OYAIB                               $8935960891618546760585096898089377896156886097652629690033599419878768424984255852521421137695754769495085398921618469764914237729576710889307470954692315601571866328742408488796145771039574397444873926883379666840494456194839899502761180282430561362538663182006432392949099112239702124912922930
Chimps on a Typewriter              $176504338999287847159247017725770908273849738720252130115528568718490320252556133502528055177870
Greedy B*****d                      $17689013777381240
Illiterate Dividend Investor        $2367418699671980
Lucky Number 6                      $4382725536910
Lone Accountant                     $90954970320
Buy/Reinvest                        $127330
Technical Analysis Robot            $126930
Dollar Cost Averager                $106130
Fibonacci                           $69930
Novice Broker                       $28130
Buy Low                             $6130
Naive Statistician                  $6130
Fallacious Gambler                  $6130
Passive Trader                      $4980
Half More or Nothing                $4920
Monkeys on a Typewriter             $66

Sehen Sie sich Diagramme der einzelnen Teilnehmer an


Verwandte aber das Gameplay und gewinnt Kriterium ist auf diese Herausforderung sehr unterschiedlich.


Kommentare sind nicht für eine längere Diskussion gedacht. Diese Unterhaltung wurde in den Chat verschoben .
Dennis

Für mich wird die Formel als [Math Processing Error] in Rot angezeigt . Ist es auch für andere so? Wenn ja, ist es vielleicht ein Problem mit der Frage.
Captain Man

2
Es könnte sich lohnen, die Ergebnisse über beispielsweise 10 bis 100 Spiele zu mitteln, um den Einfluss des Glücks zu verringern. Oder vielleicht würde das die Herausforderung zu sehr verändern.
mbrig

1
Wäre es möglich, dass die Punktzahlen log2 / log10 sind? Dies würde es viel einfacher machen, die Ergebnisse zu vergleichen. (Ich surfe mit meinem Handy und die Exponenten sind vom Bildschirm verschwunden.)

1
Ich denke, dass sogar 10-100 zu wenig sind, aber ich spiele gerne viele Spiele. Um dies zu ermöglichen, müssten Sie das Format der Herausforderung ändern, das jetzt nicht mehr zulässig ist.
Nathan Merrill

Antworten:


11

Der erfahrene gierige Idiot

PHP, das auf PHP> = 7 getestet wurde, sollte auch auf früheren Versionen funktionieren.

<?php

class StickExchange
{
    private $dbFile;
    private $sharePrice;
    private $shares;
    private $balance;
    private $overdraft;

    public function __construct($sharePrice, $shares, $balance, $round)
    {
        $this->dbFile = __FILE__ . '.txt';
        $this->sharePrice = gmp_init($sharePrice);
        $this->shares = gmp_init($shares);
        $this->balance = gmp_init($this->parseScientificNotationToInt($balance));
        $this->overdraft = gmp_init(1000);

        $action = 'b';

        if ($round == 1) {
            $this->buy();
        } elseif ($round == 1000) {
            $this->sell();
        } else {
            $content = $this->getDbContent();
            $lastPrice = gmp_init($content['price']);
            $secondLastPrice = gmp_init($content['last_price']);
            $lastAction = $content['action'];

            $shareAndLastCmp = gmp_cmp($this->sharePrice, $lastPrice);
            $lastAndSecondLastCmp = gmp_cmp($lastPrice, $secondLastPrice);

            if ($shareAndLastCmp > 0 && $lastAndSecondLastCmp > 0) {
                if ($lastAction == 'b') {
                    $this->sell();
                    $action = 's';
                } else {
                    $this->buy();
                }
            } elseif ($shareAndLastCmp < 0 && $lastAndSecondLastCmp < 0) {
                if ($lastAction == 'b') {
                    $this->sell();
                    $action = 's';
                } else {
                    $this->skip();
                }
            } elseif ($shareAndLastCmp > 0) {
                $this->sell();
                $action = 's';
            } elseif ($shareAndLastCmp < 0) {
                $this->buy();
            } else {
                $this->skip();
            }
        }

        $this->setDbContent([
            'action' => $action,
            'price' => gmp_strval($this->sharePrice),
            'last_price' => isset($lastPrice) ? gmp_strval($lastPrice) : '0',
        ]);
    }

    private function parseScientificNotationToInt($number)
    {
        if (strpos($number, 'e+') !== false) {
            $sParts = explode('e', $number);
            $parts = explode('.', $sParts[0]);
            $exp = (int)$sParts[1];

            if (count($parts) > 1) {
                $number = $parts[0] . $parts[1];
                $exp -= strlen($parts[1]);
            } else {
                $number = $parts[0];
            }

            $number = gmp_init($number);
            $pow = gmp_pow(gmp_init(10), $exp);
            return gmp_strval(gmp_mul($number, $pow));
        } elseif (strpos($number, 'e-') !== false) {
            return sprintf('%d', $number);
        } else {
            $parts = explode('.', $number);
            return $parts[0];
        }
    }

    private function getDbContent()
    {
        return unserialize(file_get_contents($this->dbFile));
    }

    private function setDbContent($content)
    {
        file_put_contents($this->dbFile, serialize($content));
    }

    private function buy()
    {
        $realBalance = gmp_add($this->balance, $this->overdraft);
        $sharesToBuy = gmp_div($realBalance, $this->sharePrice);
        $this->stdout('b' . gmp_strval($sharesToBuy));
    }

    private function sell()
    {
        $this->stdout('s' . gmp_strval($this->shares));
    }

    private function skip()
    {
        $this->stdout('b0');
    }

    private function stdout($string)
    {
        $stdout = fopen('php://stdout', 'w');
        fputs($stdout, $string);
        fclose($stdout);
    }
}

new StickExchange($argv[1], $argv[2], $argv[3], $argv[4]);

Eine aktualisierte Version von "The Greedy Idiot" mit neu strukturiertem Verhalten und Fehlerbehebungen im Zusammenhang mit der Arbeit mit riesigen Zahlen.

Anmerkungen:

  • Speichern Sie es in einer Datei und führen Sie es folgendermaßen aus: php C:\path\path\stack_exchange.php 10 5 100 1
  • Dieses Skript erstellt eine Textdatei mit demselben Namen wie die Skriptdatei und wird .txtan das Ende angehängt. Führen Sie daher bitte einen Benutzer mit der entsprechenden Schreibberechtigung im Skriptpfad aus.
  • Eine einfache Anleitung zum Installieren von PHP 7.2 unter Windows: http://www.dorusomcutean.com/how-to-install-php-7-2-on-windows/
  • Um mit sehr großen Zahlen arbeiten zu können, musste ich GMP verwenden , daher sollten diese beiden Zeilen php.iniunkommentiert sein (das Semikolon am Zeilenanfang sollte entfernt werden, wenn es nicht bereits vorhanden ist):
    • ; extension_dir = "ext"
    • ;extension=gmp

1
Wow, danke für diesen Link! Ich habe mich gefragt: D
Beta Decay

1
@BetaDecay: Kein Problem. Übrigens müssen Sie nur bis zu Schritt 2 (Test PHP ist installiert) gehen, mit dem Sie Ihre Installation überprüfen php -v. Der Rest wird dafür nicht benötigt. Ich glaube, Sie werden viel Mühe haben, so viele verschiedene Sprachen für diese Herausforderung einzurichten! Ich würde es niemals wagen, so etwas zu tun: D
Night2

@BetaDecay Wäre es nicht einfacher, TryItOnline als Docker-Container zu installieren?
NieDzejkob

@NieDzejkob Möglicherweise, aber es wird wahrscheinlich nützlich sein, diese Sprachen installiert zu haben
Beta Decay

1
Herzlichen Glückwunsch, Sie haben konsequent jeden anderen Teilnehmer geschlagen!
Beta-Zerfall

19

Schimpansen Auf Einer Schreibmaschine

import random
from sys import argv

share_price = int(argv[1])
share_count = int(argv[2])
balance = float(argv[3])

x = random.random()
if x < 0.5:
    max_buy = balance / share_price
    buy_count = int(max_buy * random.random())
    print('b' + str(buy_count))
else:
    sell_count = int(share_count * random.random())
    print('s' + str(sell_count))

Schimpansen sind schlauer als Affen, sie kaufen keine Aktien, die sie sich nicht leisten können, oder verkaufen Aktien, die sie nicht haben.

Ansonsten immer noch ziemlich zufällig.

Mit python3 ausführen, sollte aber (?) Auch mit python2 funktionieren


1
Sie mögen schlauer sein, aber haben sie mehr Glück?
Woohoojin

Bei allen meinen Tests hat sich dieser als erfolgreich
erwiesen

26
Ich bin sehr gespannt, wie dies die erste Runde um mehr als 20 Größenordnungen gewann
mbrig

Ich mag es, es auf die Kunst der Einfachheit zurückzuführen. Alle anderen übertreiben ihre Bots.
Skidsdev

1
Das hat aus Versehen so viel Liebe bekommen: P
Night2

10

OYAIB

from sys import argv

share_price = float(argv[1])
shares      = int(argv[2])
cash        = float(argv[3])
cur_round   = int(argv[4])
tot_rounds  = 1000.0

investments = shares * share_price
total_assets = investments + cash

target_cash = round(cur_round / tot_rounds * total_assets)

if target_cash > cash:
  shares_to_sell = min(shares, round((target_cash - cash) / share_price))
  print('s%d' % shares_to_sell)
else:
  shares_to_buy = round((cash - target_cash) / share_price)
  print('b%d' % shares_to_buy)

In Anlehnung an das alte Sprichwort "Eigenes Alter in Anleihen" versucht dieses Programm, dasselbe zu tun. Auf diese Weise sind wir am Ende des Spiels keiner Marktvolatilität ausgesetzt.

Edit: Betrachtet man den Controller, so zeigt sich, dass wir nur volle Aktien kaufen / verkaufen können, aber einen gebrochenen Kontostand haben können.


Willkommen bei PPCG!
Beta Decay

Danke! Lassen Sie mich wissen, wenn etwas nicht in Ordnung ist.
just_browsing

Möglicherweise möchten Sie eine zusätzliche Bedingung hinzufügen, die besagt, dass Sie in der letzten Runde alle Ihre Aktien verkaufen (was investmentsin Ihrer Punktzahl nicht berücksichtigt wird).
Riking

2
Das ist das Schöne an OYAIB, das macht es automatisch. Das target_cash ist ein Prozentsatz der total_assets, abhängig davon, an welchem ​​Punkt im "Leben" es ist. Am Ende der Laufzeit entspricht target_cash 100% von total_assets, sodass alle von ihm gehaltenen Aktien verkauft werden.
just_browsing

9

Einsamer Buchhalter

buy-sell.py:

from sys import argv

Price = int(argv[1])
Shares = int(argv[2])
Balance = float(argv[3])
Round = int(argv[4])

if Round % 2 == 0: print('s' + str(Shares))
if Round % 2 == 1: print('b' + str(int((Balance + 1000) / Price)))

Speichert nichts in buy-sell.txt.

In ungeraden Runden kauft es so viele Aktien wie möglich. In geraden Runden verkauft es alle seine Aktien.

Die Absicht ist, zuerst den Aktienkurs zu erhöhen, indem so viele Aktien wie möglich gekauft und dann diese Aktien verkauft werden, um mehr Geld zu bekommen. Es funktioniert, weil die letzte Runde gerade ist (Runde 1000).

Auch wenn der Aktienkurs 5nach jedem Rundenpaar derselbe bleibt (vorausgesetzt, der Bot ist allein, daher Lone Accountant ), erhöht sich der Kontostand des Bots, da der Verkaufspreis höher als der Kaufpreis ist und ein größerer Kontostand zu dem führt Fähigkeit, mehr Aktien zu kaufen. Es ist ein Teufelskreis, aber in guter Weise (für mich).

Die größte Schwachstelle ist, dass böse Bots mitspielen und verkaufen, um den Aktienkurs zu senken (nicht sicher, ob es auch für sie gut ist). In diesem Fall kann der Bot mit einem Kontostand von -890 USD verbleiben, vorausgesetzt, es gibt genügend böse Bots. Dieser Buchhalter möchte wirklich ihre Seelenruhe. ;-)


1 zu 1 Ich bin mir nicht sicher, ob dies möglich ist. Es ist nicht einfach, auch wenn Sie den Buchhalter LA vollständig verstehen und versuchen, dem entgegenzuwirken. In einem Massenspiel, in dem Sie zahlenmäßig unterlegen sind, können Sie ausmanövriert werden.
Yakk

@Yakk Andere haben dies schon in meinen Testläufen geschlagen.
Erik der Outgolfer

1 gegen 1? Ich bin verwirrt; Ich bin nicht in der Lage herauszufinden, wie ein Gegner reich genug werden kann, um die Kursschwankungen umzukehren, oder sogar zu verhindern, dass er im Laufe der Zeit an Größe zunimmt, ohne einen Haufen Ressourcen zu verbrennen (während LA das Opfer nicht bringt, wird dies schwieriger halt). Kannst du auf das Gameplay verweisen, dass LA eins zu eins verloren hat?
Yakk

@Yakk Ich habe es noch nicht einzeln getestet. Es gibt auch einen Chatraum, in dem wir darüber diskutieren können, wenn Sie möchten.
Erik der Outgolfer

Wäre es robuster, nichts zu tun, wenn Sie Aktien haben und der Preis niedriger ist als in der vorherigen Runde, oder wenn Sie Geld haben und der Preis höher ist? Es würde davor schützen, nicht mit anderen, ähnlichen Bots synchron zu sein. Ich verstehe auch nicht, wie man das eins zu eins schlagen kann.
JollyJoker

5

Der Passivhändler

from sys import argv

share_price = int(argv[1])
balance = float(argv[3])
round_num = int(argv[4])

if round_num == 1:
    print('b%s' % str(int(balance / share_price)))
else:
    print('b0')

Dieser Typ ist in dieser ganzen Sache mit den "Aktien" nicht groß, aber er hat gehört, dass er mit der Zeit ein bisschen Geld bekommt, das mehr ergibt, als er ausgegeben hat.

Er wird genug Aktien kaufen, um auf 0 USD zu steigen (kein Überziehungskredit für diesen Kerl, er ist kein Gunna, der sich mit ein wenig Gewinn verschuldet) und dann die Dividenden aufbauen lassen

Mit python3 ausführen, sollte aber (?) Auch mit python2 funktionieren.


1
Ich denke, Sie sollten Ihre 15 Aktien mindestens in der letzten Runde verkaufen.
Kaldo

14
@Kaldo nah, er hat es längst vergessen, dass er zu diesem Zeitpunkt einmal Aktien gekauft hat
Skidsdev

5

Prozent Trader Python3

(funktioniert vielleicht in python2)

import sys
args=sys.argv

price=int(args[1])
held=int(args[2])
money=int(args[3])
roundNum=int(args[4])
prevPrice=0

if roundNum==1:
    print("b"+str((money+1000)//price))
else:
    if roundNum==1000:
        print("s"+str(held))
    else:
        with open("percentageTrader.dat","r") as f:
            prevPrice=int(f.read())
        if(price>prevPrice):
            toSell=int(held*int(1000000*(price-prevPrice))/(price))//1000000
            print("s"+str(toSell))
        if(price<prevPrice):
            toBuy=int(((money+1000)//price)*int(1000000*(prevPrice-price))//(prevPrice))//1000000
            print("b"+str(toBuy))
        if(price==prevPrice):
            print("b0")

with open("percentageTrader.dat","w") as f:
    f.write(str(price))

Anweisungen zum Laufen

  • Speichern Sie als filename.py
  • Mit Python ausführen filename.py price #shares balance round #

Wie es funktioniert

  • In der ersten Runde kauft der Bot so viele Aktien, wie er sich leisten kann.
  • Wenn der Preis steigt, verkauft der Bot einen Prozentsatz der Aktien, der der prozentualen Preiserhöhung entspricht (berechnet aus dem neuen Wert).
  • Wenn der Preis sinkt, kauft der Bot einen Prozentsatz der maximalen Aktien, die er kaufen könnte, gleich dem prozentualen Preisrückgang (berechnet aus dem vorherigen Wert).
  • Verkauft alles um die 1000

Änderungen sollten hoffentlich die durch die Gleitkommadivision verursachten Probleme beseitigen


4

Der naive Statistiker

Made for Python 3 funktioniert möglicherweise in Python 2

from sys import argv
from math import floor

# Save an entry to the stock history
def save_history(price):
    with open('stockhistory.txt', 'a') as f:
        f.write(str(price) + '\n')

# Load the stock history
def load_history():
    with open('stockhistory.txt', 'r') as f:
        return [float(line.strip()) for line in f]

# Calculate average price rise/fall streak length
def average_streak(history, condition):
    streaks = []
    current_streak = 0
    last_price = history[0]
    for price in history[1:]:
        if condition(last_price, price):
            current_streak += 1
        elif current_streak:
            streaks += [current_streak]
            current_streak = 0
        last_price = price
    if current_streak:
        streaks += [current_streak]
    return sum(streaks) / len(streaks) if streaks else None

# Calculate the current streak length
def current_streak(history, condition):
    streak = 0
    while streak < len(history) - 1 and condition(history[-streak - 2], history[-streak - 1]):
        streak += 1
    return streak

def run(share_price, share_count, balance, round_number):
    save_history(share_price)

    # Sell all shares if it is the last round
    if round_number == 1000:
        print('s' + str(int(share_count)))
        return

    # Buy as many shares as possible if the price is down to one, as there's
    # nothing to lose
    if share_price == 1:
        buy_count = int(balance + 1000)
        print('b' + str(buy_count))
        return

    history = load_history()

    # Calculate the average and current rise/fall streaks
    average_rise = average_streak(history, lambda a, b: a <= b)
    current_rise = current_streak(history, lambda a, b: a <= b)
    average_fall = average_streak(history, lambda a, b: a >= b)
    current_fall = current_streak(history, lambda a, b: a >= b)

    # Do nothing if there's no analyzed data
    if not average_fall or not average_rise:
        print('b0')
        return

    # Buy shares if the current rise streak is as long as or longer than average
    if current_rise > current_fall and current_rise >= average_rise:
        buy_count = (balance + 1000) / share_price
        print('b' + str(int(buy_count)))
        return

    # Sell shares if the current fall streak is as long as or longer than average
    if current_fall > current_rise and current_fall >= average_fall:
        print('s' + str(int(share_count)))
        return

    # Otherwise, do nothing    
    print('b0')

run(*map(float, argv[1:]))

Dies ist ein naiver Statistiker, der versucht, die Aktienkurse vorherzusagen, indem er nur kauft / verkauft, wenn der Kurs länger als gewöhnlich gestiegen / gefallen ist, während er Aktien kauft, wenn der Kurs auf eins gesunken ist und alle Aktien in der letzten Runde verkauft.


4

Der Dollar kostet durchschnittlich

(getestet mit Python 3.7)

Erster Beitrag in Codegolf, also sag mir, ob ich etwas falsch gemacht habe.

Die Grundidee ist, wenn möglich eine Aktie pro Runde zu kaufen und am Ende alle Aktien zu verkaufen.

from sys import argv
share_price = int(argv[1])
share_count = int(argv[2])
balance = float(argv[3])
round = int(argv[4])

if round < 1000:
    if balance > share_price-1000:
        print("b1")
    else:
        print("b0")
else:
    print("s" + str(share_count))

4

Equalizer

from sys import argv
p, n, b, r = map(int, argv[1:])
c = p*n
print "bs"[(c+b)/2>b] + str(int(abs(((c-b)/2)/p))) if r < 999.5 else "s" + str(int(n))

Aufteilung der finanziellen Mittel auf Bargeld und Aktien in jeder Runde mit Ausnahme der letzten. Ich glaube , dass diese Strategie eine mathematisch fundierte Art und Weise zu sein , zumindest macht etwas Geld, aber ich kann falsch nachgewiesen werden.

Es kann Bugs geben, die ich nicht gefunden habe. Auch etwas golfen.


Ihr Programm hat Probleme mit den großen Zahlen, daher würde ich vorschlagen, die Zeile p, n, b, r = map(float, argv[1:])inp, n, b, r = map(int, argv[1:])
Beta Decay

@BetaDecay erledigt
Aidan F. Pierce

4

Affen Auf Einer Schreibmaschine

import random

cmd = ['b', 's'][int(random.random() * 2)]
num = str(int(random.random() * 1000000))
print("%s%s" % (cmd, num))

Es ist ein Haufen Affen auf Schreibmaschinen. Verkauft oder kauft zufällig X Aktien, wobei:
0 <= X <= 1,000,000

Mit python3 ausführen, sollte aber (?) Auch mit python2 funktionieren


4
Warum nicht cmd=random.choose(['b','s'])und verwenden num = str(random.randint(0, 1000000))?
Beta Decay

1
Weil ich faul bin
Skidsdev

1
warum nicht einfachimport lazy
Woohoojin

das Ganze könnte auf from random import randint, choice;print("{}{}".format(choice(["b", "s"]), randint(0, 1e6)));-P
Aaron F

6
Ja, aber dies ist keine Golf-Herausforderung
Skidsdev

4

Kaufen Sie günstig

(Python 2 oder 3)

import random

def run(price, shares, balance, round_):
    # We get no value from our leftover shares at the end, so sell them all.
    if round_ == 1000:
        print('s' + str(int(shares)))
        return

    # If the price is low enough, buy everything we can.
    if price <= 20 + round_ * 60:
        print('b' + str((balance + 1000) // price))
        return

    # If we have no shares, wait for the price to drop.
    if shares == 0:
        print('b0')
        return

    # Sometimes sell shares so we can buy if the price gets low again.
    if random.random() < 0.4:
        print('s1')
        return

    # Otherwise, just wait for a better price.
    print('b0')


if __name__ == '__main__':
    import sys
    run(*[float(x) for x in sys.argv[1:]])

3

Falscher Spieler

(Python 2 oder 3)

import random

def run(price, shares, balance, round_):
    # We get no value from our leftover shares at the end, so sell them all.
    if round_ == 1000:
        print('s' + str(int(shares)))
        return

    # For the first round, just watch.
    if round_ == 1:
        with open('fg.txt', 'w') as f:
            f.write('1 0 10')
        print('b0')
        return

    # Get the state.
    with open('fg.txt') as f:
        direction, streak, previous = map(int, f.read().strip().split())
    change = price - previous

    # If the market isn't moving, wait for it to get hot again.
    if change == 0:
        print('b0')
        return

    # Keep track of the market direction.
    if (change > 0) == (direction > 0):
        streak += 1
    else:
        streak = 0
        direction *= -1

    # If the market's been going one way for too long, it has to switch, right?
    if streak > 5:
        if direction > 0:
            print('s' + str(shares // 2))
        else:
            print('b' + str((balance + 1000) // price // 2))
    # Otherwise, the market's too volatile.
    else:
        print('b0')

    # Save the state.
    with open('fg.txt', 'w') as f:
        f.write('%d %d %d' % (direction, streak, price))


if __name__ == '__main__':
    import sys
    run(*[float(x) for x in sys.argv[1:]])

3

Der (Dyalog) APL-Bauer

r←apl_stock_farmer args
 round←¯1↑args
 :If 1=round
     (buyPrice sellPrice)←10 0
     bought←1
     (currPrice shares balance)←3↑args
     r←'b10'
 :ElseIf 1000=round
     r←'s',⍕shares
 :Else
     (currPrice shares balance)←3↑args
     :If (currPrice>buyPrice)∧bought
         bought←0
         sellPrice←currPrice
         r←'s',⍕shares
     :ElseIf (currPrice<sellPrice)∧~bought
         bought←1
         buyPrice←currPrice
         r←'b',⍕⌊(1000+balance)÷currPrice
     :Else
         r←'b0'
     :End
 :End

Ein TradFn, der jede mögliche Aktie in der ersten Runde kauft und nur verkauft, wenn der aktuelle Preis der Aktie höher ist als der Preis, für den sie gekauft wurden. Nach dem Verkauf kauft der Bot nur Aktien, die billiger sind als der Preis, für den er zuletzt Aktien verkauft hat.

Das liegt daran, dass der Buchhalter des Bauern ihm sagte, dass Sie so mit Aktien handeln. "Niedrig kaufen, hoch verkaufen" und all das Zeug.

Haftungsausschluss

Dies ist mein erster Versuch einer KotH-Herausforderung, und da ich hier im Grunde nur APL mache, habe ich beschlossen, damit fortzufahren.

Allerdings bin ich mir nicht ganz sicher, ob dies neben den anderen Bots ausgeführt werden kann, da es sich um einen Tradfn handelt und nicht direkt in eine CMD / Bash-Shell eingegeben werden kann.

Um dies in Bash auszuführen, benötigen Sie den folgenden Befehl:

$ echo apl_stock_farmer args | dyalog 'stock_exchange.dws' -script

Wo:

apl_stock_farmer ist der Name der Funktion in der ersten Codezeile.

argsist ein Vektor von durch Leerzeichen getrennten Argumenten (in der ersten Runde wäre dies der Fall 10 5 100 1).

dyalog ist der Pfad zur ausführbaren Dyalog-Datei

'stock_exchange.dws'ist der Name (oder Pfad, wenn sich die Datei nicht in demselben Verzeichnis befindet, in dem die Shell geöffnet ist) des Arbeitsbereichs, der die Funktion enthält. Diese Arbeitsbereichsdatei erhalten Sie, indem Sie einen leeren Arbeitsbereich öffnen )ed apl_stock_farmer, den obigen Code eingeben , einfügen und dann a )save <path>. Ich kann diese Arbeitsbereichdatei auch bereitstellen, wenn das einfacher wäre.

-script Dies ist nur ein Argument, das dyalog veranlasst, den angegebenen Code auszuführen und auf stdout zu drucken, ohne die REPL zu öffnen.

Leider habe ich keine Möglichkeit gefunden, es mit Windows CMD oder Powershell zum Laufen zu bringen, also habe ich es mit Git Bash ausgeführt. Ich bin nicht sicher, wie machbar es ist, diesen Bot im Wettbewerb zu platzieren, aber ich mag diesen Code viel zu sehr, um ihn nicht zu posten.


Entschuldigung, ich habe nur die unregistrierte Version von Dyalog APL, daher bin ich mir nicht sicher, ob dies als Teilnehmer am Wettbewerb funktioniert
Beta Decay

@BetaDecay Ich verstehe, keine Probleme da. Ich fand auch heraus, dass Sie die Pynapl-Bibliothek verwenden können , um diesen Code auszuführen. Die Details finden Sie unter "Zugriff auf APL über Python", insbesondere unter "Definieren eines Tradfn mit Python", und es sieht ziemlich einfach aus.
J. Sallé

3

Analphabetischer Dividendeninvestor

import random
from sys import argv

price = float(argv[1])
shares = int(argv[2])
cash = float(argv[3])
round = int(argv[4])

# buy 1st round, sell last round
if round == 1:
    print('b' + str(int((cash + 1000) / price)))
elif round == 1000:
    print('s' + str(shares))

# round right before dividend: sell
elif round % 5 == 4:
    print('s' + str(shares))

# 1 round after dividend: buy
elif round % 5 == 0:
    print('b' + str(int((cash + 1000) / price)))

# 2 rounds after dividend: 50/50 sell/try to buy
elif round % 5 == 1:
    if random.random() < 0.5:
        print('s' + str(shares))
    else:
        print('b' + str(int((cash + 1000) / price)))

# 3 rounds after dividend: sell if own shares (didn't sell last round), else buy
elif round % 5 == 2:
    if shares > 0:
        print('s' + str(shares))
    else:
        print('b' + str(int((cash + 1000) / price)))

# otherwise, 4 rounds after dividend, buy
else:
    print('b' + str(int((cash + 1000) / price)))

Angenommen, die Leute haben nach der Dividende mehr Bargeld, sodass sie mit größerer Wahrscheinlichkeit kaufen werden. Verkauft direkt vor Dividenden, kauft direkt danach. Durchläuft einen weiteren Verkaufs- / Kaufzyklus in den anderen 3 Runden.


Betrachtet man den Controller, werden die Dividenden jede Runde nach der vierten und nicht nur nach jeder fünften Runde ausgezahlt. Ihr Zyklus sollte weiterhin funktionieren, aber wahrscheinlich nicht so, wie Sie es beabsichtigt haben.
Veskah

Wenn Sie kaufen, nachdem andere kaufen, kaufen Sie am Ende, wenn es teurer ist.
Freitag,

Vielen Dank @Veskah. Musste auch eine r1 / r1000-Logik hinzufügen.
brian_t

@ fəˈnəˈtɪk - wenn die Leute die Runde nach der Dividende kaufen, möchten auch Sie diese Runde kaufen und anschließend verkaufen, nein?
brian_t

Es gibt auch keine Runde nach Dividenden, da Sie jede Runde nach dem 4. Dividenden erhalten.
Freitag,

3

Kaufen / Reinvestieren Sie so viel wie möglich!

Ähnlich wie bei meinem Dollar-Cost-Averager, der überraschenderweise ziemlich durchschnittlich war, kauft dieser in jeder Runde so viele Aktien, wie erschwinglich sind, und verkauft sie nur in der letzten Runde.

from sys import argv

share_price = int(argv[1])
share_count = int(argv[2])
balance = float(argv[3])
round = int(argv[4])


if round < 1000:
    if balance > share_price-1000:
        buy_count = int((balance+1000)/share_price)
        print("b"+str(buy_count))
    else:
        print("b0")
else:
    print("s" + str(share_count))

Hey, du hast hier einen Fehler mit deiner Einrückung. Meinten Sie, den if balance > share_price-1000:Block einzurücken oder nicht?
Beta Decay

Ja. Meine kleinere Bearbeitung scheint meine Formatierung gestört zu haben. Wird behoben, sobald ich auf einem PC zurück bin
Barbarian772

2

Anfänger Broker (aber bekommt die Grundidee)

se_stock_exchange.rb:

DATA_FILE = $0.sub /\.rb$/, ".data"
NUM_ROUNDS = 1000

share_price, num_shares, money, round = ARGV.map &:to_i

order = "s0"

if round == NUM_ROUNDS
  puts "s#{num_shares}"
  exit
end

if File.exists? DATA_FILE
  last_price, trend, bought_price = File.read(DATA_FILE).lines.map &:to_i
else
  last_price = 0
  trend = -1
  bought_price = 0
end

if (new_trend = share_price <=> last_price) != trend
  case trend
  when -1
    order = "b#{(money + 1000) / share_price}"
    bought_price = [bought_price, share_price].max
  when 1
    if share_price > bought_price
      order = "s#{num_shares}"
      bought_price = 0
    end
  end
  trend = new_trend
end

File.open(DATA_FILE, "w") { |f| f.puts share_price, trend, bought_price }

puts order

Wartet, bis sich der Preis ändert, und kauft / verkauft dann alles. Ich meine, das ist es, was es in Day Trading für Dummies zu tun gibt. Hinweis: Dies ist wahrscheinlich ein echtes Buch, und das ist wahrscheinlich etwas, was jemand davon bekommen könnte .

Speichert Daten in se_stock_exchange.data. Ausführen mit ruby se_stock_exchange.rb ${SHARE_PRICE} ${SHARES} ${MONEY} ${ROUND}(Ersetzen der entsprechenden Werte).


Dies ist mein erster Versuch bei KotH, also lass es mich wissen, wenn ich alles falsch mache.
iamnotmaynard


Ich bekomme diesen Fehler:se_stock_exchange.rb:24:in `<main>': undefined method `+' for nil:NilClass (NoMethodError)
Erik der Outgolfer

4
@BetaDecay: Schade, dass der zweite Vorname des Autors nicht mit einem 'A' beginnt.
3D1T0R

3
@NieDzejkob: Wenn es ein 'A' wäre: "Ann A. Logue" ist analog zu " Analog ".
3D1T0R

2

Halb mehr oder gar nichts

def run(price, shares, balance, cur_round):
    if cur_round==1000:
        print('s'+str(int(shares)))
        return

    if cur_round==1:
        with open('HalfMoreOrNothing.dat', 'w') as f:
            f.write(str(int(price)))
        print('b'+str(int((balance+1000)/price)))
        return

    if shares==0:
        with open('HalfMoreOrNothing.dat', 'w') as f:
            f.write(str(int(price)))
        print('b'+str(int((balance+1000)/price)))
        return

    with open('HalfMoreOrNothing.dat', 'r') as f:
        bought_price=int(f.read())
    if price>=bought_price*1.5:
        print('s'+str(int(shares)))
        return

    print('b0')

if __name__ == '__main__':
    import sys
    run(*[float(x) for x in sys.argv[1:]])

Ich verwende Python selten. Lassen Sie mich wissen, wenn dies irgendwo einen Fehler verursacht.

Die Strategie besteht darin, zu warten, bis der Aktienkurs mindestens 50% über dem Preis zum Zeitpunkt des Erwerbs liegt, sie dann zu verkaufen und sofort neue Aktien zu kaufen, damit sie auf die Erhöhung des Aktienkurses warten können.

Hoffentlich werden die Leute, die Schimpansen sind, gegen Ende nicht anfangen, Aktien zu verkaufen ... (es scheint, dass die meisten Bots nur auf den richtigen Moment warten, was auch immer das ist)


2

Fibonacci

Ich habe dies in Python 3 umgeschrieben, um es einfacher zu machen. Hoffnungsvoll!

import math
from sys import argv

price = float(argv[1])
shares = int(argv[2])
balance = float(argv[3])
roundNum = int(argv[4])

fibonacci = [2,3,5,8,13,21,34,55,89,144,233,377,610,987]
if (roundNum == 1):
    buy = int((balance+1000)/price)
    print('b' + str(buy))
elif (roundNum in fibonacci) and roundNum % 2 == 1 and balance > 0:
    buy = int((balance/price)/2)
    print('b' + str(buy))
elif ((roundNum in fibonacci) and roundNum % 2 == 0) or roundNum % 100 == 0:
    if (roundNum == 1000):
        sell = shares
        print('s' + str(sell))
    else:
        sell = math.ceil(shares/2)
        print('s' + str(sell))
else:
    print('b0')

Es kauft die Hälfte der maximalen Aktienanzahl, die erschwinglich ist, wenn die Runde einer ungeraden Fibonacci-Zahl entspricht, und verkauft die Hälfte der verfügbaren Aktien, wenn die Runde einer geraden Fibonacci-Zahl entspricht, sowie alle 100 Runden. Verkauft alle Aktien in Runde 1000. Ansonsten wartet es nur. Kauft Aktien nur bei positivem Saldo.


Hey, ich bekomme den FehlerError in roundNum%%2 : non-numeric argument to binary operator Execution halted
Beta Decay

@BetaDecay Ich habe den Code aktualisiert, mit dem das Problem behoben werden kann. Gib mir Bescheid.
Robert S.

1

Gierig B ***** d

# Gready one...
from sys import argv

SMA_PERIOD = 5
LAST_BUY_DAY = 985
LAST_SELL_DAY = 993

# Save an entry to the stock history
def save_history(price):
    with open('db.txt', 'a') as f:
        f.write(str(price) + '\n')

# Load the stock history
def load_history():
    with open('db.txt', 'r') as f:
        return [float(line.strip()) for line in f]

def get_sma(d, n):
    l = d[-n:]
    return int(sum(l) / len(l))


def buy(price, account):
    if account + 1000 > 0:
        print 'b' + str(int((account + 1000) / price))
        return
    print 'b0'

def sell(holdings):
    print 's'+ str(int(holdings))


def run(price, holdings, account, day):

    save_history(price)
    d = load_history()

    if price <= get_sma(d, SMA_PERIOD) and day < LAST_BUY_DAY:
        return buy(price, account)

    if price > get_sma(d, SMA_PERIOD):
        return sell(holdings)

    if day >= LAST_SELL_DAY:
        return sell(holdings)

    # Otherwise, do nothing    
    print 'b0'


run(*map(float, argv[1:]))  

Er wird alles geben, wenn es billig ist, und alles verkaufen, sobald der Preis steigt ...


Ihr Code ist überall. Zuerst geben Sie print-Anweisungen zurück, aber Sie übergeben auch drei Argumente, für sell()die nur eines
Beta Decay

Tippfehler mit drei Argumenten zu verkaufen () ... Was ist nun Ihre Sorge mit der Rückgabe von Druckaussagen?
Arek S

Nur dass sie unnötig sind
Beta Decay

Einige argumentieren, sie helfen mit Lesbarkeit
Arek S

Sie haben es wegen Abzügen nicht in die Ergebnisse aufgenommen? Afaik Tippfehler in Sale () Definition wird nicht aufhören zu arbeiten ... Ich behebe das übrigens
Arek S

1

Technischer Analyseroboter

Ich habe Betriebswirtschaft studiert und versucht, die einfachste Methode zur Analyse eines Aktienmarktes zu finden (die technische Analyse). Nach der Theorie müssen Sie nur alle Minima des Graphen analysieren, um festzustellen, ob es einen Trend gibt (nach oben oder nach unten). Während eines Aufwärtstrends muss man kaufen und während eines Abwärtstrends muss man verkaufen.

Ich glaube nicht, dass diese Methode zu gut funktioniert, aber probieren wir es aus :)

import sys
from sys import argv

share_price = int(argv[1])
share_number = int(argv[2])
bank_account = float(argv[3])
round_number = int(argv[4])

max_buy_greedily = (1000 + bank_account) / share_price
minima = []

def log():
    f = open("log_technical_analysis.txt","a+")
    f.write("%d;" % share_price)

def analyze():
    f = open("log_technical_analysis.txt","r+")
    line = f.readline()
    values = line.split(";")
    values.pop()
    for i in range(len(values) - 1):
        if i > 0 and int(values[i-1]) > int(values[i]) and int(values[i+1]) > int(values[i]):
            minima.append(int(values[i]))
    if len(minima) >= 3 and minima[len(minima) - 1] > minima[len(minima) - 2] and minima[len(minima) - 2] > minima[len(minima) - 3]:
        print('b' + str(int(max_buy_greedily)))
    elif len(minima) >= 3 and minima[len(minima) - 1] < minima[len(minima) - 2] and minima[len(minima) - 2] < minima[len(minima) - 3]:
        print('s' + str(share_number))
    else:
        print('b0')

if round_number >= 994:
    print('s' + str(share_number))
    sys.exit(0)

if share_price <= 15:
    print('b' + str(int(max_buy_greedily)))
    log()
    sys.exit(0)

log()
analyze()
sys.exit(0)

Getestet mit python3


2
Viel Glück! Dies ist weit entfernt von einem normalen Markt: D
Beta Decay

1
@BetaDecay haha ​​yeah:] aber Sie würden sich fragen, wie zufällig die meisten Leute ihr Geld an der Börse ausgeben (oder Bitcoin): D
Solenya

1

Glückszahl 6

EDIT: Oh ffs, ich denke, dass ich die Verkaufszahlen nicht auf int umgerechnet habe, das war eines meiner Probleme.

Wahrscheinlich mein letzter Beitrag, es sei denn, ich langweile mich bei der Arbeit und mache etwas etwas raffinierter, aber ich falle wie die raffinierten Bots schon in die Nischen.

Dieser Typ verkauft im Grunde alle 6 Runden einen Teil seiner Aktien, weil Hey 6 seine Glückszahl ist.

from sys import argv
import random

share_price = int(argv[1])
share_count = int(argv[2])
balance = float(argv[3])
round = int(argv[4])
x = random.uniform(1,2)

if round == 1 or round == 1000:
    print("s"+str(share_count))
elif round % 6 == 0 and share_price >= 10:
    sell = int(share_count/x)
    print("s"+str(sell))
elif balance > share_price-1000:
    buy_count = int((balance+1000)/share_price)
    print("b"+str(buy_count))
else:
    print("b0")
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.