Börse KoTH

23

An der Börse dreht sich alles um die Geschwindigkeit des Wissens. Im Gegensatz zu früheren Herausforderungen ist der aktuelle Aktienkurs nicht zufällig: Er wird von den Spielern bestimmt. Wenn Sie eine unterbewertete Aktie vor allen anderen identifizieren können, haben Sie sich selbst ein Geldverdienen-Programm geschrieben.

Der Preis bezieht sich auf die Menge, für die die Aktien gehandelt werden, während sich der Wert auf den Betrag bezieht, den die Aktie am Ende des Spiels wert ist.

Jeder Spieler beginnt mit 1000 von jeder Aktie und 0 relativem Nettowert. Jede Aktie hat einen geheimen Wert und Ihre Punktzahl am Ende des Spiels ist(stockValue for each ownedStock) + netWorth . Ihr Nettovermögen kann negativ sein. In einem N-Spieler-Spiel gibt es N Aktien.

Schritte:

Das Spiel folgt den folgenden Schritten:

  1. Sie erhalten den geheimen Wert einer einzelnen Aktie.
  2. Sie machen ein Angebot, X von Y Aktien für $ Z zu verkaufen
  3. Alle Spieler erhalten die Angebote und jeder kann eines zur Annahme auswählen
  4. Alle Spieler werden über akzeptierte Angebote informiert
  5. Fahren Sie mit Schritt 2 fort

Jeder der Schritte wird nachstehend ausführlich beschrieben:

  1. void secretValue(int stockType, int value):

    • Der Wert, den Sie lernen, wird keinem anderen Spieler mitgeteilt.
    • Der Wert liegt zwischen 0und1000
    • Niedrige Werte treten eher auf als hohe (quadratische Gleichverteilung)
  2. Offer makeOffer(List<Stock> currentStock)

    • Sie können zurückkehren null, um kein Angebot zu machen.
  3. Offer acceptOffer(List<Offer> offers)

    • Sie können zurückkehren null, um keine von ihnen zu akzeptieren
    • Wenn keine Angebote verfügbar sind, wird dies nicht aufgerufen
    • Wenn Sie akzeptieren, sinkt Ihr Nettovermögen um $ Z (kann negativ werden) und Sie erhalten X von Y Aktien. Das Gegenteil tritt beim Verkäufer ein.
    • Wenn Sie ein Angebot annehmen, erfolgt der Umtausch sofort und das Angebot wird entfernt, sodass weitere Spieler es nicht annehmen können.
  4. void acceptedOffers(List<Offer> offers)

    • Beinhaltet auch Ihre akzeptierten Angebote

Statische Variablen oder das Schreiben in Dateien sind nicht zulässig. (Keine dauerhaften Daten von Spiel zu Spiel) Nicht ernsthafte Konkurrenten sind erlaubt.

Schnittstellen:

public final class Stock {
    public Stock(int stockType, int amount);
    public int getType();
    public int getAmount();
    public Stock minus(Stock other);
    public Stock plus(Stock other);
    public Stock minus(int amount);
    public Stock plus(int amount);
    public Stock setAmount(int amount);
}
public class Offer {
    public Offer(Stock offer, int payment);
    public Stock getOffer();
    public int getPayment();
}

Nicht-Java-Beiträge:

  • Alle Anrufe bestehen aus zwei Leitungen: Die erste Linie ist die Funktion aufgerufen wird: SecretValue, MakeOffer, AcceptOffer, AcceptedOffers, SetRandom, und die zweite Linie die eigentlichen Daten enthält.
  • Die Aktien werden mit einem formatierten :Begrenzer: stockType:stockAmount.
  • Angebote werden mit einem @Trennzeichen formatiert :offer@price
  • Listen werden mit einem ;Trennzeichen formatiert
  • SecretValueist mit einem :Trennzeichen formatiert :stockType:value
  • RandomSeedwird verwendet, um Ihre Einreichung deterministisch zu machen. Wenn Ihre Einsendung Zufälligkeit verwendet, verwenden Sie bitte den als Startwert übergebenen Integer-Wert!
  • Alle Funktionsaufrufe benötigen eine Antwort. Wenn die Antwort nulloder ist void, geben Sie eine leere Zeichenfolge zurück.
  • Fügen Sie ein hinzu command.txt, das die Befehlszeilenargumente für die Ausführung Ihrer Übermittlung enthält

Wertung

Spiele mit 1000 Runden werden mehrmals gespielt. Die Spieler werden nach dem ELO-System gewertet und mit Spielern mit ähnlichen Fähigkeiten gepaart. Der Spieler mit der höchsten endgültigen ELO-Punktzahl gewinnt! (Ich habe das System so modifiziert, dass bei jedem Spiel die ELO-Punkte für jedes Spielerpaar aktualisiert werden.)

Der Controller enthält einen Autodownloader, so wenden Sie sich bitte Ihre Vorlage mit einem Header beginnen: Name, Language. Wenn Ihre Übermittlung nicht in Java erfolgt, sollte jeder Codeblock mit dem Namen der Datei beginnen. (Ausgenommen die Befehlsdatei, die der erste Block in Ihrem Beitrag sein sollte)

Laufen

Es gibt zwei Möglichkeiten, dieses Projekt auszuführen:

  1. Laden Sie den Quellcode herunter, kompilieren Sie ihn und starten Sie ihn. Die Quelle finden Sie auf Github . Laufgit clone --recursive https://github.com/nathanmerrill/StockExchange.git

  2. Laden Sie die ausführbare JAR-Datei herunter. Die Beiträge sollten in Ihrem aktuellen Arbeitsverzeichnis im /submissionsOrdner abgelegt werden . Sie können nur die JAR , nur die Einreichungen oder beides herunterladen

Melden Sie sich an run, um das Projekt auszuführen (Standardoption), oder melden Sie sich an download, um alle Einsendungen herunterzuladen, die bisher von dieser Frage betroffen waren.

Anzeigetafel

1.  1308.1220497323848  Cheater
2.  1242.0333695640356  InsideTrader
3.  1158.3662658295411  UncleScrooge
4.  1113.8344000358493  BlackMarket
5.  1051.8370015258993  DartMonkey
6.  983.0545446731494   WarGamer
7.  939.457423938002    Spammer
8.  901.4372529538886   DumbBot
9.  859.0519326039137   ShutUpAndTakeMyMoney
10. 852.9448222849587   VincentKasuga
11. 718.2112067329083   Profiteer
Nathan Merrill
quelle
Aktieneigenschaften
@AgentCrazyPython besser?
Nathan Merrill
stimmen aktuelle preise mit früheren preisen überein?
29.
1
Ein Chatroom wäre dankbar.
TheNumberOne

Antworten:

13

Betrüger, Java

Versucht, nichts für Geld zu verkaufen.

import java.util.List;
import java.util.Random;
import com.ppcg.stockexchange.*;

public class Cheater extends Player {
    private Random random = new Random();

    public Offer acceptOffer(List<Offer> offers) {
        return null;
    }

    public Offer makeOffer(List<Stock> currentStock){
        Stock stock = randomStock();
        int price = random.nextInt(100) + 1;
        return new Offer(stock.setAmount(0), price);
    }
}
CommonGuy
quelle
5
Und so passiert die Weltwirtschaftskrise! Ich konnte sehen, wie viele Bots zerstört wurden, die günstig einkaufen ...
Socratic Phoenix
Glückwunsch! Ich habe einen kritischen Fehler behoben und jetzt ist dieser Bot an erster Stelle!
Nathan Merrill
Wow, die anderen Bots sind dann nicht gut genug, dass dieser blöde Bot gewinnen kann
halbe
8

WarGamer, Java

Nach einer oberflächlichen Prüfung der Regeln habe ich entschieden, dass der primäre Gewinnzug nicht darin besteht, zu spielen. Jeder, der Aktien zum Verkauf anbietet, kennt wahrscheinlich den Preis und wird vom Verkauf profitieren. Es kann umgeschaltet werden, so dass es "Scherz" -Angebote zum Verkauf einer Aktie für Integer macht.

import java.util.List;
import com.ppcg.stockexchange.*;
import com.ppcg.kothcomm.game.AbstractPlayer;
import com.ppcg.kothcomm.utils.Tools;

import java.util.List;

public class WarGamer extends Player {
static final boolean FRAUD = false;
    /**
     * @param offers All available offers
     * @return An offer you want to accept, or null if you want to accept neither.
     */
    public Offer acceptOffer(List<Offer> offers){
        return null;
    }

    public Offer makeOffer(List<Stock> currentStock){
    if(FRAUD)
    return new Offer(new Stock(0,1),Integer.MAX_VALUE);
        //defraud shut up and take my money            
    return null;
    }
}
Rohan Jhunjhunwala
quelle
1
Dies würde wahrscheinlich gut funktionieren, außer ich gehe davon aus, dass es Einträge geben wird, die etwas höher liegen. Das gibt es normalerweise.
Geobits
Dies wird nicht kompiliert.
Rainbolt
@Rainbolt es hat die Abhängigkeiten. Sie müssen sicherstellen, dass vorhanden sind.
Rohan Jhunjhunwala
@ Rainbolt welche Compiler-Fehler bekommen Sie
Rohan Jhunjhunwala
1
Ich bin mir nicht sicher, ob der Teil, in dem Sie den anderen
Witzbot austricksen,
5

ShutUpAndTakeMyMoney, Java

import java.util.List;
import com.ppcg.stockexchange.*;

public class ShutUpAndTakeMyMoney extends Player {
    public ShutUpAndTakeMyMoney() {}

    public Offer acceptOffer(List<Offer> offers) {
        try {
            return offers.get(0);
        } catch (Exception ex) {
            return null;
        }
    }
    public Offer makeOffer(List<Stock> stock) {
        return null;
    }
}

Es nimmt jedes Angebot an.

TuxCrafting
quelle
Eigentlich danke für Ihren Bot
Rohan Jhunjhunwala
6
haben +1 für mich reich zu machen
Rohan Jhunjhunwala
1
Es scheint mir, dass dies nicht wirklich mit der Forderung vereinbar ist, dass jede Antwort " ein ernstzunehmender Anwärter auf die verwendeten Gewinnkriterien sein sollte ".
Peter Taylor
2
@PeterTaylor Es ist ernst, es ist 5. in der Rangliste
TuxCrafting
Dies ist wohl ein selbstmörderischer Einstieg , da zu erwarten ist, dass andere Bots Aktien für mehr verkaufen, als sie wert sind, was dazu führt, dass Sie Aktien weit über ihrem tatsächlichen Preis kaufen.
Mego
4

DumbBot, Java

Verwenden Sie diesen Bot, wenn Sie Ihren eigenen erstellen. Bietet seinen geheimen Bestand zu einem reduzierten Preis an.

import java.util.List;
import com.ppcg.stockexchange.*;
public class DumbBot extends Player {
    public Offer acceptOffer(List<Offer> offers) {
        return null;
    }
    public Offer makeOffer(List<Stock> currentStock){
        return new Offer(currentStock.get(secretStockType).setAmount(1), Math.max(1, secretStockValue - 5));
    }
    public void secretValue(int stockType, int value) {
        super.secretValue(stockType, value);
    }
    public void acceptedOffers(List<Offer> acceptedOffers) {
    }
}
Nathan Merrill
quelle
1
Scheint, als wollte ich, dass er mit meinem Geld
umgeht
Bitte
erstelle
@AgentCrazyPython warum?
Nathan Merrill
@ NathanMerrill rep profitiert von diesem Dummy-Bot
noɥʇʎԀʎzɥʇʎԀʎ
@AgentCrazyPython Ich möchte nicht, dass die Leute dies bearbeiten ... Ich interessiere mich nicht wirklich für Repräsentanten, also zögern Sie nicht, die Stimme zu erheben (oder abzustimmen)
Nathan Merrill
3

python_starter, Python 3

Verwenden Sie dies als Ausgangspunkt für alle Python- (oder andere Sprach-) Programme

Nimmt ein zufälliges Angebot an.

Befehlsdatei:

python3 starter.py

Programm:

starter.py
import random
from functools import total_ordering


LIST_DELIMITER = ';'
STOCK_DELIMITER = ':'
OFFER_DELIMITER = '@'


@total_ordering
class Stock:
    @staticmethod
    def parse(string: str):
        return Stock(*map(int, string.split(STOCK_DELIMITER)))

    def __init__(self, stock_type: int, amount: int):
        self.type = stock_type
        self.amount = max(amount, 0)

    def __str__(self):
        return str(self.type)+STOCK_DELIMITER+str(self.amount)

    def __eq__(self, other):
        return self.amount == other.type

    def __lt__(self, other):
        return self.amount < other.amount

    def update(self, amount) -> 'Stock':
        return Stock(self.type, amount)

    def __mul__(self, other: int) -> 'Stock':
        return self.update(self.amount*other)

    def __floordiv__(self, other: int) -> 'Stock':
        return self.update(self.amount//other)

    def __add__(self, other: int) -> 'Stock':
        return self.update(self.amount+other)

    def __sub__(self, other: int) -> 'Stock':
        return self.update(self.amount-other)


class Offer:
    @staticmethod
    def parse(string: str) -> 'Offer':
        try:
            offer, payment = string.split(OFFER_DELIMITER)
        except ValueError:
            raise Exception("Cannot unpack "+string)
        return Offer(Stock.parse(offer), int(payment.strip()))

    def __init__(self, offer: Stock, payment: int):
        self.offer = offer
        self.payment = payment

    def __str__(self):
        return str(self.offer)+OFFER_DELIMITER+str(self.payment)


def read_stock_value(value: str):
    global hidden_price, hidden_stock
    stock, price = value.split(STOCK_DELIMITER)
    hidden_price = float(price)
    hidden_stock = int(stock)


def process_input():
    handlers = {
        "SecretValue": read_stock_value,
        "RandomSeed": read_seed,
        "MakeOffer": make_offer,
        "AcceptOffer": accept_offer,
        "AcceptedOffers": accepted_offers,
    }
    method = input().strip()
    data = input().strip()
    output = handlers[method](data)
    if output is not None:
        print(str(output))
    else:
        print()


def read_seed(seed: str):
    random.seed(int(seed))


def start():
    while True:
        process_input()


hidden_stock = None
hidden_price = None


def make_offer(current_stock: str):
    current_stock = map(Stock.parse, current_stock.split(LIST_DELIMITER))
    pass


def accept_offer(available_offers: str):
    available_offers = list(map(Offer.parse, available_offers.split(LIST_DELIMITER)))
    return random.sample(available_offers, 1)[0]


def accepted_offers(offers: str):
    offers = map(Offer.parse, offers.split(LIST_DELIMITER))
    pass


if __name__ == "__main__":
    start()
Nathan Merrill
quelle
1
das ist zu kompliziert.
29.
2
Das meiste davon ist Helferzeug. Wenn Sie es in Python schreiben, müssen Sie nur die unteren 3 Funktionen implementieren.
Nathan Merrill
was tut es?
noɥʇʎԀʎzɥʇʎԀʎ
Der Bot akzeptiert einen zufälligen Bestand. Das Hilfsprogramm führt das Parsen / Codieren durch und bietet Klassen für Angebot / Bestand an.
Nathan Merrill
... und es gewinnt: /
noɥʇʎԀʎzɥʇʎԀʎ
3

VincentKasuga, Java

Ich bin mir nicht sicher, ob mein Java gültig ist. Lesen Sie bitte.

Wie es funktioniert

- Wenn Sie alle Aktien besitzen, können Sie den Kurs der Aktie festlegen. Sie sind der einzige Verkäufer. 1. Kaufen Sie alle Aktien. 2. Stellen Sie den Kurs aller Aktien so ein, dass sie beim letzten Tick super hoch sind. 3. GEWINN! - Das ist normalerweise nicht möglich, weil ...

  • Der Preis würde normalerweise ins Unendliche steigen ... aber es gibt eine Grenze!
  • ... (weitere Gründe zu kommen)

Wie es funktioniert, v2

  • Der Preis wird von einem anarchistischen Staat künstlich auf ein Maximum festgelegt
  • Das ist wirtschaftlich schlecht
  • Der Bot sagt es nicht voraus - er nutzt einen inhärenten Fehler in der Struktur des Marktes aus!

Machen

  • Begeben Sie sich mehrmals auf den Markt! Muahaha!

FAQ

F: Wer ist Vincent Kasuga?

A: Er hat alle Zwiebeln und Zwiebel-Futures in den USA gekauft. (alle in ein geheimes Lagerhaus stecken) Die Branche wird freigelassen - gib mir X Millionen, oder ich setze den Preis auf ein himmelhohes Niveau, und du wirst alle bankrott gehen.

Aber er hörte dort nicht auf.

Dann schloss er heimlich den Zwiebel-ETF kurz (wetten, dass er sinken würde). Er verkaufte alle Zwiebeln auf einmal und lieferte sie physisch in Tausenden von Lastwagen an die Börse. Der Zwiebelbeutel kostet weniger als die Zwiebeln. Er hat WIEDER Millionen gemacht. Kurz, der Hudson River war voller Zwiebeln.

Er ist eine echte Person.

Der Code

import com.ppcg.stockexchange.Offer;
import com.ppcg.stockexchange.Player;
import com.ppcg.stockexchange.Stock;

import java.util.List;

public class VincentKasuga extends Player {
    private int knownStock;
    private int knownPrice;
    private int corneredStockType = -1;
    private int corneredLikelehood = 0;
    private boolean marketCornered;
    private int ticks;

    public Offer acceptOffer(List<Offer> offers) {
        if (!marketCornered) {
            Offer maxOffer = null;
            int maxAmount = 0;
            if (corneredStockType == -1) {
                for (Offer offer: offers) {
                    if (offer.getOffer().getAmount() > maxAmount) {
                        maxAmount = offer.getOffer().getAmount();
                        maxOffer = offer;
                    }
                }
            } else {
                for (Offer offer: offers) {
                    if (offer.getOffer().getAmount() > maxAmount && offer.getOffer().getType() == corneredStockType) {
                        maxAmount = offer.getOffer().getAmount();
                        maxOffer = offer;
                    }
                }
            }


            if (maxOffer == null) {
                // may have cornered the market
                corneredLikelehood++;
                if (corneredLikelehood == 5) {
                    // probably cornered the market
                    marketCornered = true;
                }
            }
            return maxOffer;
        } else {
            // who needs offers when the market is cornered!?
            return null;
        }
    }

    public Offer makeOffer(List<Stock> currentStock) {
        ticks++;
        if (ticks >= 999) {
            // SELL SELL SELL!
            return new Offer(new Stock(corneredStockType, 1000), 1000);
        } else {
            return null;
        }
    }

    public void secretValue(int stockType, int value) {
        knownStock = stockType;
        knownPrice = value;
        if (stockType == corneredStockType) {
            if (knownPrice == 1000) {
                corneredLikelehood += 3;
            } else if (knownPrice < 900){
                // didn't corner the market.
                corneredLikelehood = 0;
            }
        }
    }
}

"Ich habe den Goldmarkt in die Enge getrieben, Mr. Bond!"

noɥʇʎԀʎzɥʇʎԀʎ
quelle
Ich habe einen Auto-Downloader für Bots eingebaut. Bitte geben Sie Ihren Code in einen Code-Block ein. Wenn es nicht passt, ist das in Ordnung.
Nathan Merrill
@ NathanMerrill Ich verstehe. Aber kompiliert es?
29.
@ NathanMerrill fertig. Probs kompiliert nicht. interessante Strategie, nicht wahr? Und eine Lehre in Wirtschaft!
29.
for (offer: offers)->for (Offer offer: offers)
Nathan Merrill
corneredStockType == nullist auch nicht gültig. ein intkann nicht sein null.
MegaTom
2

Spammer, Java

import java.util.List;
import java.util.ArrayList;
import com.ppcg.stockexchange.*;

public class Spammer extends Player {
    private boolean panic = false;

    public Offer acceptOffer(List<Offer> offers) {
        for (Offer offer : offers) {
            if (this.panic || offer.getPayment() < 20)
                return offer;
        }
        return null;
    }
    public Offer makeOffer(List<Stock> currentStock) {
        if (currentStock.size() > 1) { // Don't sell all the stock
            this.panic = false;
            return new Offer(currentStock.get(secretStockType).setAmount(1), 1);
        }
        this.panic = true; // BUY
        return null;
    }
}

Spammen Sie den Markt mit wirklich billigen Aktien und kaufen Sie Aktien nur, wenn der Preis unter 20 liegt. Wenn die Aktienanzahl auf 1 fällt, wird versucht, etwas zu kaufen.

TuxCrafting
quelle
funktioniert gut in der Weltwirtschaftskrise
noɥʇʎԀʎzɥʇʎԀʎ
... wie gewinnt das !?
noɐɹƆzɥʇʎԀʎ
2

DartMonkey, Java

(Nicht konkurrierend: Es wird nicht gewinnen und ich habe bereits eine andere Antwort)

Dart Affe mag es Dinge zu werfen ... und es gibt einen großen Haufen spitzer Stöcke neben ihm. Er sieht etwas Papier an der Wand. Bam! Bam! Bam! In kürzester Zeit hat Dart Monkey 80 Darts geworfen! Die Hälfte der Pfeile ist rot und die andere Hälfte ist blau und es sind Zufallszahlen darauf! Dart Monkey sieht einen Computer ... Dart Monkey gibt die Zahlen ein. Pfeilaffe mag Zahlen. Dart Affe verdient etwas Geld mit seinen Darts ...


Im Ernstfall initialisiert DartMonkey ein ganzzahliges Array mit einer Länge, die doppelt so lang ist wie die Anzahl der Aktien. Er speichert eine Zahl für die Menge an Aktien, die er kaufen / verkaufen möchte, und eine Zahl für den Preis der Aktie. Anschließend verkauft er abwechselnd Aktien aus dem Array und nimmt Angebote entsprechend dem Array an. Wenn er keine Vorräte aus dem Array hat, wird er nichts anbieten, und wenn er keine Angebote aus dem Array hat, wird er nichts annehmen.


Diese Antwort wurde von @TheNumberOne inspiriert, der im Chat Dart-Affen erwähnte

import com.ppcg.stockexchange.Offer;
import com.ppcg.stockexchange.Player;
import com.ppcg.stockexchange.Stock;

import java.util.List;
import java.util.Random;

public class DartMonkey extends Player {
    private int basePrice = 100;
    private int numStocks;
    private int[] dartBoard;
    private boolean first = true;

    @Override
    public Offer acceptOffer(List<Offer> offers) {
        for(Offer offer : offers) {
            Stock stock = offer.getOffer();
            int type = stock.getType();
            int amount = stock.getAmount();
            int price = offer.getPayment();
            if(this.dartBoard[type] < 0 && amount <= -this.dartBoard[type] && price <= this.dartBoard[type + this.numStocks]) {
                this.dartBoard[type] = 0;
                return offer;
            }
        }
        return null;
    }

    @Override
    public Offer makeOffer(List<Stock> stocks) {
        if(this.first) {
            this.first = false;
            this.numStocks = stocks.size();
            this.dartBoard = new int[this.numStocks * 2];
            Random random = this.getRandom();
            for (int i = 0; i < 20; i++) {
                int index = random.nextInt(this.dartBoard.length / 2);
                this.dartBoard[index] = random.nextInt(1001);
                this.dartBoard[this.numStocks + index] = random.nextInt(1001);
            }

            for (int i = 0; i < 20; i++) {
                int index = random.nextInt(this.dartBoard.length / 2);
                this.dartBoard[index] = -random.nextInt(1001);
                this.dartBoard[this.numStocks + index] = random.nextInt(1001);                
            }
        }

        for (Stock stock : stocks) {
            int type = stock.getType();
            if(this.dartBoard[type] > 0) {
                Offer offer = new Offer(stock.setAmount(this.dartBoard[type]), this.basePrice + this.dartBoard[type + this.numStocks]);
                this.dartBoard[type] = 0;
                this.dartBoard[type + this.numStocks] = 0;
                return offer;
            }
        }

        return null;
    }

}
Sokratischer Phönix
quelle
Wie ich sehe, sind Sie zufällig die Wall Street entlanggelaufen?
Rohan Jhunjhunwala
Dies ist wohl eine selbstmörderische Einreise , die nicht erlaubt ist.
Mego
1
@Mego Ich verstehe nicht, wie ... Ein Selbstmord-Eintrag würde Aktien für 0 Dollar verkaufen. Dieser Eintrag bestimmt, was er zufällig kauft und verkauft. Was definitiv nicht gegen die Regeln verstößt ...
Socratic Phoenix
2

InsideTrader, Java

InsideTrader schaute sich nur um und bemerkte, dass jeder versuchte kreativ zu sein. Aber er hat etwas Kreatives getan: das tun, was erwartet wird.

Dieser Bot kauft, wenn es sich "lohnt", weil er einige "interne Dokumente" "geliehen" hat, um "Investitionsentscheidungen" zu "leiten".

To-Do und wie es im Code funktioniert. ;)

Der Code"

import java.util.List;

import com.ppcg.stockexchange.*;

public class InsideTrader extends Player {
    public String coverStory = "I can tell the good companies from the bad ones.";
    private String theTruth = "I'm cheating. (but so is everyone else)";
    private String ambitions = "Learn to \"follow the market\"";  // don't steal this idea
    private int secretStock = -1;
    private int secretStockValue = -1;

    private int appraiseOffer(Offer offer) {
        /* get how much the offer is worth, 0 if it's not the secret stock */
        if (offer.getOffer().getType() != secretStock ||offer.getOffer().getAmount() == 0) {
            return 0;
        }
        return (offer.getPayment()/offer.getOffer().getAmount())  // price per stock...
                - secretStockValue  // minus value of stock.
                ;
    }
    public Offer acceptOffer(List<Offer> offers) {
        Offer bestOffer = null;
        int bestOfferValue = -1;
        for (Offer offer :
                offers) {
            int value = appraiseOffer(offer);
            if (value > bestOfferValue && value > 0) {
                bestOfferValue = value;
                bestOffer = offer;
            }
        }
        return bestOffer;
    }

    public Offer makeOffer(List<Stock> currentStock) {
        return new Offer(new Stock(0,1), Integer.MAX_VALUE);
    }

    public void secretValue(int stockType, int value) {
        secretStock = stockType;
        secretStockValue = value;
    }

    public void acceptedOffers(List<Offer> acceptedOffers) {

    }
}
noɥʇʎԀʎzɥʇʎԀʎ
quelle
Sie können diese zusätzlichen Klassen nicht am Anfang der Datei haben ... es ist syntaktisch ungültig ... sie können ohne public an das Ende angehängt werden, denke ich
Socratic Phoenix
Error on line 50: modifier private not allowed here Error on line 54: modifier private not allowed here. Ich würde nur die Klassen entfernen und es verlängern lassenPlayer
Nathan Merrill
Nur eine Anmerkung, einige neue Bots bieten Aktien mit Beträgen von Null an, sodass Ihr Bot eine ArithimeticException (/ by zero) aus der Rückgabe von appraiseOffer auslöst ... fügen Sie vielleicht einen Scheck hinzu oder so?
Socratic Phoenix
@SocraticPhoenix Danke, wird behoben.
noɥʇʎԀʎzɥʇʎԀʎ
Herzlichen Glückwunsch, dieser Bot ist momentan auf dem zweiten Platz!
Nathan Merrill
2

Wall Street, Kotlin

Beginnt mit einem hohen und einem niedrigen Kaufpreis und wechselt allmählich zu dem, was der Preis für richtig hält. Sie können dies auch als Vorlage verwenden, um Ihre eigenen in Kotlin zu erstellen.

Hinweis: Es gibt hier einen Fehler, den ich scheinbar nicht zuverlässig reproduzieren kann. Wenn mein Programm abstürzt oder Probleme hat, pinge mich bitte im Chat an und verlinke ein Pastebin des Inhalts vonsubmissions/other/WallStreet/log.txt

kotlinc WallStreet.kt
kotlin WallStreetKt
WallStreet.kt
import java.io.FileOutputStream
import java.io.PrintStream
import java.util.*

val LOGGER = PrintStream(FileOutputStream("log.txt", true))
const val DEBUG = false

const val LOG_GAME_HEADER = """
###############
#STARTING GAME#
###############"""

data class Stock(val type : Int, val amount : Int) {

    operator fun minus(amount : Int) = copy(amount = this.amount - amount)
    operator fun plus(amount: Int) = copy(amount = this.amount + amount)
    fun setAmount(amount: Int) = copy(amount = amount)

    operator fun minus(other : Stock) : Stock {
        assert(type == other.type)
        return copy(amount = this.amount - other.amount)
    }

    operator fun plus(other : Stock) : Stock {
        assert(type == other.type)
        return copy(amount = this.amount + other.amount)
    }

    override fun toString() = "$type:$amount"
}

data class Offer(val offer: Stock, val payment: Int) {
    override fun toString() = "$offer@$payment"
}

fun parseStock(repr : String) : Stock {
    val data = repr.split(":").map { it.toInt() }
    return Stock(data[0], data[1])
}

fun parseOffer(repr: String) : Offer {
    val data = repr.split("@")
    return Offer(parseStock(data[0]), data[1].toInt())
}

fun parseOffers(repr: String) = if (repr == "") emptyList<Offer>() else repr.split(";").map { parseOffer(it) }


interface Player {
    fun secretValue(stockType: Int, value: Int)
    fun makeOffer(currentStock: List<Stock>) : Offer?
    fun acceptOffer(offers: List<Offer>) : Offer?
    fun acceptedOffers(offers: List<Offer>)

    var random : Random
}

fun main(args : Array<String>) {

    try {

        if (DEBUG) {
            LOGGER.println(LOG_GAME_HEADER)
        }
        //Change bot name here
        val player = WallStreet()

        while (true) {
            val function = readLine()
            function ?: return
            val line = readLine()!!
            if (DEBUG) {
                LOGGER.println("\nInput:")
                LOGGER.println(function)
                LOGGER.println(line)
            }
            var result : Any
            try {
                result = when (function) {
                    "SecretValue" -> {
                        val data = line.split(":").map { it.toInt() }
                        player.secretValue(data[0], data[1])
                    }
                    "MakeOffer" -> player.makeOffer(line.split(";").map { parseStock(it) }) ?: ""
                    "AcceptOffer" -> player.acceptOffer(parseOffers(line)) ?: ""
                    "AcceptedOffers" -> player.acceptedOffers(parseOffers(line))
                    "RandomSeed" -> player.random = Random(line.toLong())
                    else -> return        //Exit program
                }
                if (function == "AcceptOffer" && result.toString() !in line) {
                    throw Exception("Offer not among available offers!!!!\nResult: $result\nParsed Available Offers: ${parseOffers(line)}")
                }
            } catch (e : Exception) {
                LOGGER.println("Turn #${player.turn}")
                LOGGER.println("\nInput:")
                LOGGER.println(function)
                LOGGER.println(line)
                throw e
            }

            if (result == Unit) {
                result = ""
            }
            if (DEBUG) {
                LOGGER.println("Output:")
                LOGGER.println(result)
            }

            println(if (result == Unit) "" else result)
        }
    } catch (e : Exception) {
        e.printStackTrace(LOGGER)
        throw e
    } finally {
        LOGGER.close()
    }
}


// ###################################################
// #          Put program logic below here.          #
// ###################################################


const val DEFAULT_STOCK_VALUE = 333
const val MAX_TURNS = 1000
const val MAX_STOCK_VALUE = 1000

class WallStreet : Player {

    var secretStockType = 0
    var secretStockValue = 0
    override var random = Random()


    var turn = 0
    val stockPriceStatistics = mutableMapOf<Int, DoubleSummaryStatistics>()

    override fun secretValue(stockType: Int, value: Int) {
        secretStockType = stockType
        secretStockValue = value
    }

    override fun makeOffer(currentStock: List<Stock>): Offer {
        val stock = currentStock[random.nextInt(currentStock.size)]
        val type = stock.type
        val amount = random.nextInt(stock.amount)
        val price = getSellPrice(type) * amount
        return Offer(Stock(type, amount), Math.ceil(price).toInt())
    }

    override fun acceptOffer(offers: List<Offer>): Offer? {
        var bestOffer : Offer? = null
        var mostProfit = 0.0
        for (offer in offers) {
            val offerProfit = profitOfOffer(offer)
            if (offerProfit > mostProfit) {
                bestOffer = offer
                mostProfit = offerProfit
            }
        }
        if (bestOffer != null && bestOffer !in offers) {
            throw IllegalStateException("Tried to accept non-existent offer.\nOffer:  $bestOffer\nAvailable Offers: ${offers.joinToString(";")}")
        }
        return bestOffer
    }

    override fun acceptedOffers(offers: List<Offer>) {
        turn++
        for ((stock, payment) in offers) {
            val stats = stockPriceStatistics.getOrPut(stock.type) { DoubleSummaryStatistics() }
            for (i in 1..stock.amount) {
                stats.accept(payment.toDouble() / stock.amount)
            }
        }
    }

    private fun getSellPrice(type: Int): Double {
        var price = getPrice(type)
        if (price < 1000) {
            price += (1000 - price) * (MAX_TURNS - turn) / MAX_TURNS
        }
        return if (type == secretStockType) Math.max(secretStockValue.toDouble(), price) else price
    }

    private fun getPrice(type: Int): Double {
        return stockPriceStatistics[type]?.average ?: DEFAULT_STOCK_VALUE.toDouble()
    }

    private fun profitOfOffer(offer: Offer): Double {
        return getBuyPrice(offer.offer.type) * offer.offer.amount - offer.payment
    }

    private fun getBuyPrice(type: Int): Double {
        var price = getPrice(type)
        price = price * turn / MAX_TURNS
        return if (type == secretStockType) Math.min(secretStockValue.toDouble(), price) else Math.min(price, MAX_STOCK_VALUE.toDouble())
    }

}
Die Nummer eins
quelle
command.txtbraucht den Dateinamen nicht. Netter Post!
Nathan Merrill
Ich dachte, String-Interpolation wurde mit $ {} durchgeführt, nicht nur mit $?
Socratic Phoenix
@SocraticPhoenix $funktioniert nur mit einem Variablennamen. ${}führt beliebigen Code aus. Grundsätzlich funktioniert es so oder so und ich bevorzuge ohne die Klammern.
TheNumberOne
Zu Ihrer Information: Als vorübergehende Lösung müssen Fensterbenutzer, die diese Datei ausführen möchten, die folgenden Einstellungen ändern command.txt: kotlinc-> kotlinc.batund kotlin->kotlin.bat
Nathan Merrill
Nachdem ich meinen Controller repariert hatte, gab dieser Bot eine Reihe fehlerhafter Daten zurück, und so entfernte ich sie von der Konkurrenz. Ich kann dir im Chat helfen, wenn du willst :)
Nathan Merrill
1

UncleScrooge, Java

import java.util.List;
import com.ppcg.stockexchange.*;

public class UncleScrooge extends Player {
    public Offer acceptOffer(List<Offer> offers) {
        Offer offer;
        try {
            offer = offers.get(0);
        } catch (Exception ex) {
            return null;
        }
        if (offer.getPayment() < 100)
            return offer;
        else
            return null;
    }
    public Offer makeOffer(List<Stock> currentStock){
        if (this.getRandom().nextDouble() < 0.6)
            return new Offer(currentStock.get(secretStockType).setAmount(1), Integer.MAX_VALUE);
        else
            return null;
    }
    public void secretValue(int stockType, int value) {
        super.secretValue(stockType, value);
    }
    public void acceptedOffers(List<Offer> acceptedOffers) { }
}

Verkaufen Sie Aktien zu einem wirklich hohen Preis und kaufen Sie nur, wenn der Preis unter 100 liegt.

TuxCrafting
quelle
1

Profiteur, Java

Profiteur ist für das Geld dabei, und er zählt immer Münzen. Er schätzt konservativ, wie viel Geld er hat. Er kauft dann die geheimen Aktien, wenn sie unter dem Wert liegen, oder kauft billige Aktien. Er merkt sich auch, wie viel er für alles bezahlt hat und macht immer Angebote, die über dem Aktienkurs liegen. Außerdem macht er höhere Angebote, wenn er weniger Geld hat.

Hinweis: Ich denke, ich habe das richtig gemacht, aber wenn es @ NathanMerrill nichts ausmacht, meinen Code nach Fehlern zu durchsuchen, wäre das großartig

import com.ppcg.stockexchange.Offer;
import com.ppcg.stockexchange.Player;
import com.ppcg.stockexchange.Stock;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class Profiteer extends Player {
    private List<StockInfo> onMarket;
    private List<StockInfo> stocks;
    private int money;
    private boolean first = true;

    @Override
    public Offer acceptOffer(List<Offer> offers) {
        Offer finalOffer;

        Optional<Offer> offer = offers.stream().filter(o -> o.getOffer().getType() == this.secretStockType && o.getPayment() < this.secretStockValue * o.getOffer().getAmount()).sorted((a, b) -> Integer.compare((this.secretStockValue * a.getOffer().getAmount()) - b.getPayment(), (this.secretStockValue * b.getOffer().getAmount()) - b.getPayment())).findFirst();
        if (offer.isPresent()) {
            finalOffer = offer.get();
        } else {
            finalOffer = offers.stream().sorted((a, b) -> Integer.compare(a.getPayment(), b.getPayment())).findFirst().orElse(null);
        }

        if (finalOffer == null || this.money <= finalOffer.getPayment()) {
            return null;
        } else {
            this.stocks.add(new StockInfo(finalOffer.getOffer(), finalOffer.getPayment()));
            this.refreshMoney();
            return finalOffer;
        }
    }

    @Override
    public Offer makeOffer(List<Stock> stocks) {
        if (this.first) {
            this.init(stocks);
        } else {
            this.refreshMarketList(stocks);
        }

        Optional<StockInfo> least = this.stocks.stream().sorted((a, b) -> Integer.compare(a.getBoughtPrice(), b.getBoughtPrice())).findFirst();
        Optional<StockInfo> secret = this.stocks.stream().filter(stockInfo -> stockInfo.getStock().getType() == this.secretStockType).sorted((a, b) -> Integer.compare(a.getBoughtPrice(), b.getBoughtPrice())).findFirst();

        StockInfo finalOffer;
        int price;
        if (secret.isPresent()) {
            finalOffer = secret.get();
        } else if (least.isPresent()) {
            finalOffer = least.get();
        } else {
            return null;
        }

        this.onMarket.add(finalOffer);
        this.stocks.remove(finalOffer);
        price = this.calculatePrice(finalOffer.boughtPrice);
        return new Offer(new Stock(finalOffer.getStock().getType(), finalOffer.getStock().getAmount()), price);
    }

    private int calculatePrice(int boughtPrice) {
        return (int) (boughtPrice + ((boughtPrice / (double) this.money) * this.money)) + 1;
    }

    private void refreshMarketList(List<Stock> stocks) {
        this.stocks.addAll(this.onMarket.stream().filter(stockInfo -> stocks.contains(stockInfo.getStock())).collect(Collectors.toList()));
        this.onMarket.clear();
    }

    private void refreshMoney() {
        this.money = this.stocks.stream().mapToInt(info -> this.secretStockType == info.getStock().getType() ? this.secretStockValue : 5).reduce((a, b) -> a + b).orElseGet(() -> 0) - this.stocks.stream().mapToInt(StockInfo::getBoughtPrice).reduce((a, b) -> a + b).orElseGet(() -> 0);
    }

    private void init(List<Stock> stocks) {
        this.stocks = stocks.stream().map(stock -> new StockInfo(stock, 0)).collect(Collectors.toList());
        this.onMarket = new ArrayList<>();
        this.money = 0;
        this.first = false;
        this.refreshMoney();
    }

    private static class StockInfo {
        private Stock stock;
        private int boughtPrice;

        public StockInfo(Stock stock, int boughtPrice) {
            this.stock = stock;
            this.boughtPrice = boughtPrice;
        }

        public Stock getStock() {
            return this.stock;
        }

        public int getBoughtPrice() {
            return this.boughtPrice;
        }

    }

}
Sokratischer Phönix
quelle
Sie können in die Schulden gehen und noch von Aktien ...
no --zɥʇʎԀʎ
@ AgentCrazyPython Ich weiß, aber Profiteur will es nicht riskieren
Socratic Phoenix
kann nicht rückgängig gemacht werden
noɥʇʎԀʎzɐɹƆ
@AgentCrazyPython meh, es ist okay, das Spiel macht Spaß und das ist, was zählt
Socratic Phoenix
1

MaxBot, Java

Dieser Bot versucht, aus jeder Transaktion den größten Gewinn zu machen. Beim Verkauf liegt der Preis einer unbekannten Aktie bei 300 USD, beim Kauf bei 250 USD.

import java.util.List;
import com.ppcg.stockexchange.*;
public class MaxBot extends Player {
    int toSell;
    int sellPrice;

    public void secretValue(int stockType, int value) {
        super.secretValue(stockType, value);
        toSell = stockType;
        sellPrice = (value + 1000)/2;
    }
    public Offer acceptOffer(List<Offer> offers) {
        Offer max = null;
        int maxDif = 0;
        for(Offer o: offers){
            int price = secretStockType == o.getOffer().getType()? secretStockValue: 250;
            int val = price * o.getOffer().getAmount();
            int dif = val - o.getPayment();
            if(maxDif < dif){
                max = o;
                maxDif = dif;
            }
        }
        return max;
    }
    public Offer makeOffer(List<Stock> currentStock){
        if(toSell == -1){
            return null;
        }
        int sum = 0;
        for (Stock s: currentStock){
            if(s.getType() == toSell){
                sum += s.getAmount;
            }
        }
        int n = sum - sum/2;
        return new Offer(new Stock(toSell, n), n * sellPrice);
    }
    public void acceptedOffers(List<Offer> acceptedOffers) {
        int highStock = -1;
        int highPrice = 0;
        int markup = 0;
        for(Offer o: offers){
            int trueVal = secretStockType == o.getOffer().getType()? secretStockValue: 250;
            int marketVal = o.getPayment()/o.getOffer().getAmount();
            if(marketVal - trueVal > markup){
                highStock = o.getOffer().getType();
                highPrice = marketVal;
                markup = marketVal - trueVal;
            }
        }
        toSell = highStock;
    }
}
MegaTom
quelle
1

BlackMarket, Java

Dazu gibt es nicht viel zu sagen, da diese Transaktionen ... außerhalb der Charts liegen werden, könnte man sagen.

import java.util.List;
import com.ppcg.stockexchange.*;

public class BlackMarket extends Player {
    private boolean approvedBySEC = false;
    private int ammoLeft = 30;
    public String taxView = "We want higher tax rates";
    public String excuse = "I never saw that in my life";

    public void secretValue(int drugType, int warrantForMyArrest) {
        super.secretValue(drugType, warrantForMyArrest);
        if (warrantForMyArrest != 0 || drugType == 420) {
            ammoLeft += 10;
        }
    }

    public Offer acceptOffer(List<Offer> offers) {
        for (Offer offer : offers) {
            if (this.approvedBySEC || offer.getPayment() < 9)
                return offer;
        }
        return null;
    }


    public Offer makeOffer(List<Stock> currentStock) {
        return new Offer(new Stock(0,1),420);
    }
}
Timtech
quelle
return null ist außerhalb ... bitte auch richtig einrücken.
noɥʇʎԀʎzɥʇʎԀʎ
1
@AgentCrazyPython Danke! Wir werden die "return null" abrufen, sobald es dunkel ist. Seien Sie vorsichtig mit Autos, die Ihnen für den nächsten Monat folgen.
Timtech
1
Warum die Gegenstimme? Wir belegten im letzten Wettbewerb den vierten Platz. Obwohl wir nicht genau
wissen
0

NotQuiteABanksBestFriend, Python 3

Command.txt:

python3 NotQuiteABanksBestFriend.py
NotQuiteABanksBestFriend.py
import random
from functools import total_ordering
from io import StringIO

log = StringIO()
log.write("\n\n~~~NEW GAME~~~\n\n")

LIST_DELIMITER = ';'
STOCK_DELIMITER = ':'
OFFER_DELIMITER = '@'

JAVA_MAX_INT = 2147483647

@total_ordering
class Stock:
    @staticmethod
    def parse(string: str):
        return Stock(*map(int, string.split(STOCK_DELIMITER)))

    def __init__(self, stock_type: int, amount: int):
        self.type = stock_type
        self.amount = max(amount, 0)

    def __str__(self):
        return "T%sx%s"%(self.type, self.amount)

    def __repr__(self):
        return str(self.type)+STOCK_DELIMITER+str(int(self.amount))

    def __bool__(self):
        return bool(self.amount)

    def __eq__(self, other):
        return self.amount == other.amount

    def __lt__(self, other):
        return self.amount < other.amount

    def update(self, amount) -> 'Stock':
        return Stock(self.type, amount)

    def __mul__(self, other: int) -> 'Stock':
        return self.update(self.amount*other)

    def __floordiv__(self, other: int) -> 'Stock':
        return self.update(self.amount//other)

    def __add__(self, other: int) -> 'Stock':
        return self.update(self.amount+other)

    def __sub__(self, other: int) -> 'Stock':
        return self.update(self.amount-other)


class Offer:
    @staticmethod
    def parse(string: str) -> 'Offer':
        try:
            stock, price = string.split(OFFER_DELIMITER)
        except ValueError:
            raise Exception("Cannot unpack "+string)
        return Offer(Stock.parse(stock), int(price.strip()))

    def __init__(self, stock: Stock, price: int):
        self.stock = stock
        self.price = price
        try:
            self.price_per_unit = self.price/self.stock.amount
        except ZeroDivisionError:
            self.price_per_unit = float('inf')

    def __str__(self):
        return "%s$%s"%(self.stock, self.price)

    def __repr__(self):
        return repr(self.stock)+OFFER_DELIMITER+str(int(self.price))


def read_stock_value(value: str):
    global hidden_price, hidden_stock
    stock, price = value.split(STOCK_DELIMITER)
    hidden_price = float(price)
    hidden_stock = int(stock)
    log.write("Hidden StockID: %s\nHidden Price: %s\n"%(hidden_stock, hidden_price))

def process_input():
    handlers = {
        "SecretValue": read_stock_value,
        "RandomSeed": read_seed,
        "MakeOffer": make_offer,
        "AcceptOffer": accept_offer,
        "AcceptedOffers": accepted_offers,
    }
    method = input().strip()
    data = input().strip()
    output = handlers[method](data)
    if output is not None:
        print(repr(output))
    else:
        print()

def read_seed(seed: str):
    random.seed(int(seed))

def start():
    while True:
        process_input()

hidden_stock = None
hidden_price = None

def filter_offers(offer):
    if offer.stock.amount == 0:
        return False
    if offer.price_per_unit > 1000:
        return False
    return True

def certain_profit(offer):
    stock = offer.stock
    if stock.type == hidden_stock and offer.price_per_unit < hidden_price:
        log.write("Offer, %s is certainly profitable.\n"%offer)
        return True
    return False

def make_offer(current_stock: str):
    current_stock = list(map(Stock.parse, current_stock.split(LIST_DELIMITER)))
    own_stock = [stock for stock in current_stock if stock.type == hidden_stock]
    if own_stock and own_stock[0]:
        own_stock = own_stock[0]
        amount_sold = min(random.randrange(1,50), own_stock.amount)
        price = hidden_price+random.randrange(10,50)
        return Offer(Stock(hidden_stock, amount_sold), price*amount_sold)
    sell_stock = random.choice(current_stock)
    amount_sold = min(random.randrange(1,50), sell_stock.amount)
    price = random.randrange(1000, JAVA_MAX_INT//(amount_sold or 1))
    return Offer(Stock(sell_stock.type, amount_sold), price*(amount_sold or 1))

def accept_offer(available_offers: str):
    available_offers = list(map(Offer.parse, available_offers.split(LIST_DELIMITER)))
    filtered_offers = list(filter(filter_offers, available_offers))
    profitable = list(filter(certain_profit, filtered_offers))
    rtn_list = filtered_offers
    if profitable:
        log.write("Profitable: %s\n"%profitable)
        rtn_list = profitable
    if not rtn_list:
        return None
    accepted_offer = min(rtn_list, key=lambda offer: offer.price_per_unit)
    log.write("Bidded for %s\n"%accepted_offer)
    return accepted_offer

def accepted_offers(offers: str):
    pass


if __name__ == "__main__":
    try:
        start()
    finally:
        log.close()

Versucht immer, versteckte Aktien für mehr zu verkaufen, als es wert ist.

Blau
quelle