Bourse de valeurs KoTH

23

Le marché boursier est tout au sujet de la vitesse de la connaissance. Contrairement aux défis précédents, le cours actuel n'est pas aléatoire: il est déterminé par ceux qui jouent le jeu. Si vous pouvez identifier un stock sous-évalué avant tout le monde, alors vous vous êtes écrit un programme rentable.

Le prix se réfère à combien les gens échangent le stock, tandis que la valeur se réfère à la valeur du stock à la fin du jeu.

Chaque joueur commence avec 1000 de chaque stock et 0 valeur nette relative. Chaque stock a une valeur secrète, et votre score à la fin du jeu est(stockValue for each ownedStock) + netWorth . Votre valeur nette peut être négative. Dans une partie à N joueurs, il y a N actions.

Pas:

Le jeu suit les étapes suivantes:

  1. On vous donne la valeur secrète d'un stock unique.
  2. Vous faites une offre de vente d'actions X sur Y pour $ Z
  3. Tous les joueurs reçoivent les offres et chacun peut en choisir une à accepter
  4. Tous les joueurs sont informés des offres acceptées
  5. Revenez à l'étape 2

Chacune des étapes est détaillée ci-dessous:

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

    • La valeur que vous apprenez n'est révélée à aucun autre joueur.
    • La valeur est comprise entre 0et1000
    • Les valeurs faibles sont plus susceptibles de se produire que les valeurs élevées (distribution uniforme au carré)
  2. Offer makeOffer(List<Stock> currentStock)

    • Vous pouvez revenir nullpour ne faire aucune offre.
  3. Offer acceptOffer(List<Offer> offers)

    • Vous pouvez revenir nullpour n'en accepter aucun
    • S'il n'y a pas d'offres disponibles, cela ne sera pas appelé
    • Si vous acceptez, votre valeur nette diminue de $ Z (peut devenir négative) et vous recevez X actions Y. L'inverse se produit avec le vendeur.
    • Si vous acceptez une offre, l'échange aura lieu immédiatement et l'offre sera supprimée afin qu'aucun joueur supplémentaire ne puisse l'accepter.
  4. void acceptedOffers(List<Offer> offers)

    • Comprend également vos offres acceptées

Les variables statiques ou l'écriture dans des fichiers ne sont pas autorisées. (Aucune donnée persistante d'un jeu à l'autre) Les concurrents non sérieux sont autorisés.

Interfaces:

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();
}

Soumissions non Java:

  • Tous les appels sont constituées de deux lignes: la première ligne est la fonction appelée: SecretValue, MakeOffer, AcceptOffer, AcceptedOffers, SetRandom, et la seconde ligne contenant les données réelles.
  • Les stocks sont mis en forme avec un :delimiter: stockType:stockAmount.
  • Les offres sont formatées avec un @délimiteur:offer@price
  • Les listes sont formatées avec un ;délimiteur
  • SecretValueest formaté avec un :délimiteur:stockType:value
  • RandomSeedest utilisé pour rendre votre soumission déterministe. Si votre soumission utilise l'aléatoire, veuillez utiliser la valeur entière transmise comme graine!
  • Tous les appels de fonction nécessitent une réponse. Si la réponse est nullou void, renvoyez une chaîne vide.
  • Veuillez inclure un command.txtqui donne les arguments de ligne de commande pour exécuter votre soumission

Notation

Les jeux composés de 1000 tours se dérouleront plusieurs fois. Les joueurs seront notés selon le système ELO et jumelés avec des joueurs de niveaux de compétence similaires. Le joueur avec le score ELO final le plus élevé gagne! (J'ai modifié le système pour que chaque jeu, les scores ELO soient mis à jour pour chaque paire de joueurs)

Le contrôleur comprend un AutoDownloader, donc s'il vous plaît commencer votre soumission avec un en- tête: Name, Language. Si votre soumission n'est pas en Java, chaque bloc de code doit commencer par le nom du fichier. (à l'exclusion du fichier de commandes, qui devrait être le premier bloc de votre message)

Fonctionnement

Il existe 2 façons d'exécuter ce projet:

  1. Téléchargez le code source, compilez et exécutez. Vous pouvez trouver la source sur Github . Courirgit clone --recursive https://github.com/nathanmerrill/StockExchange.git

  2. Téléchargez l'exécutable JAR. Les soumissions doivent être placées dans votre répertoire de travail actuel dans le /submissionsdossier. Vous pouvez télécharger uniquement le JAR , uniquement les soumissions , ou les deux

Passez runpour exécuter le projet (option par défaut), ou passez downloadpour télécharger toutes les soumissions loin de cette question.

Tableau d'affichage

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
la source
les propriétés du stock ne sont pas publiques,
demandez
@AgentCrazyPython mieux?
Nathan Merrill
les prix actuels sont-ils corrélés aux prix antérieurs?
noɥʇʎԀʎzɐɹƆ
1
Un salon de discussion serait apprécié.
TheNumberOne

Réponses:

13

Tricheur, Java

Essaie de ne rien vendre pour de l'argent.

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
la source
5
Et c'est ainsi que la grande dépression se produit! Je pouvais voir ça casser beaucoup de bots qui achètent pas cher ...
Socratic Phoenix
Félicitations! J'ai corrigé un bug critique, et maintenant ce bot est en premier!
Nathan Merrill
Wow, les autres bots ne sont pas assez bons alors, que ce bot stupide peut gagner
juste le
8

WarGamer, Java

Après un examen superficiel des règles, j'ai décidé que le coup gagnant principal n'est pas de jouer. Quiconque propose de vendre des actions connaît probablement le prix et profitera de la vente. Il peut être basculé de sorte qu'il fera des offres de "blague" pour vendre un stock pour Integer.MAX_VALUE dollars en espérant la fermer et prendre mon argent mordra.

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
la source
1
Cela fonctionnerait probablement très bien, sauf que je m'attends à ce qu'il y ait des entrées qui vont un peu plus haut. Il y en a généralement.
Geobits
Cela ne compile pas.
Rainbolt
@Rainbolt il a les dépendances. Vous devez vous assurer d'être présent.
Rohan Jhunjhunwala
@Rainbolt quelle erreur du compilateur obtenez-vous
Rohan Jhunjhunwala
1
Je ne suis pas sûr que la partie où vous trompez l'autre robot de plaisanterie soit dans le bon esprit ...
Maltysen
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;
    }
}

Il accepte toute offre.

TuxCrafting
la source
En fait merci pour votre bot
Rohan Jhunjhunwala
6
avoir +1 pour m'avoir enrichi
Rohan Jhunjhunwala
1
Il me semble que cela n'est pas vraiment compatible avec l'exigence selon laquelle chaque réponse doit " être un concurrent sérieux pour les critères gagnants utilisés ".
Peter Taylor
2
@PeterTaylor C'est sérieux, il est 5ème du classement
TuxCrafting
Il s'agit sans doute d'une entrée suicidaire , car il est raisonnable de s'attendre à ce que d'autres robots vendent des actions à un prix supérieur à leur valeur, ce qui vous amène à acheter des actions bien au-dessus de leur prix réel.
Mego
4

DumbBot, Java

Utilisez ce bot lors de la création du vôtre. Offre son stock secret à un prix réduit.

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
la source
1
On dirait que je veux qu'il gère mon argent
Rohan Jhunjhunwala
veuillez créer ce wiki communautaire
noɥʇʎԀʎzɐɹƆ
@AgentCrazyPython pourquoi?
Nathan Merrill
@NathanMerrill rep profitant de ce robot factice
noɥʇʎԀʎzɐɹƆ
@AgentCrazyPython Je ne veux pas vraiment que les gens éditent ça ... Je ne me soucie pas vraiment des représentants, alors n'hésitez pas à voter (ou à voter)
Nathan Merrill
3

python_starter, Python 3

Utilisez-le comme point de départ pour tous les programmes python (ou autre langage)

Accepte une offre aléatoire.

Fichier de commande:

python3 starter.py

Programme:

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
la source
1
c'est trop compliqué.
noɥʇʎԀʎzɐɹƆ
2
La plupart sont des trucs d'aide. Si vous l'écrivez en python, il vous suffit d'implémenter les 3 dernières fonctions.
Nathan Merrill
Qu'est ce que ça fait?
noɥʇʎԀʎzɐɹƆ
Le bot accepte un stock aléatoire. Le truc d'aide fait l'analyse / l'encodage, ainsi que fournit des classes pour l'offre / stock.
Nathan Merrill
... et ça gagne: /
noɥʇʎԀʎzɐɹƆ
3

VincentKasuga, Java

Je ne sais pas si mon Java est valide. S'il-vous-plaît évaluez.

Comment ça marche

- si vous possédez tous les stocks, vous pouvez définir le prix du stock. Vous êtes le seul vendeur. 1. Achetez tous les stocks. 2. Définissez le prix de tous les stocks pour être super élevé au dernier tick. 3. PROFIT! - Ce n'est normalement pas possible car ...

  • Le prix monterait généralement à l'infini ... mais il y a une limite!
  • ... (plus de raisons à venir)

Comment ça marche, v2

  • Le prix est artificiellement fixé au maximum par un état anarchiste
  • C'est mauvais économiquement
  • Le bot ne prédit pas - il exploite une faille inhérente à la structure du marché!

Faire

  • Accrochez le marché plusieurs fois! Muahaha!

FAQ

Q: Qui est Vincent Kasuga?

R: Il a acheté tous les oignons et les oignons à terme aux États-Unis. (mettez-les tous dans un entrepôt secret) Tenez l'industrie contre rançon - donnez-moi X millions ou je fixerai le prix au plus bas et vous ferez tous faillite.

Mais il ne s'est pas arrêté là.

Puis, il a secrètement court-circuité l'ETF de l'oignon (en pariant qu'il allait baisser). Il a vendu tous les oignons en même temps, les livrant physiquement dans des milliers de camions à la bourse. Le sac d'oignon coûte moins cher que les oignons. Il a fait des millions ENCORE. Bref, la rivière Hudson débordait d'oignons.

C'est une vraie personne.

Le 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;
            }
        }
    }
}

"J'ai acculé le marché de l'or, M. Bond!"

noɥʇʎԀʎzɐɹƆ
la source
J'ai inclus un téléchargeur automatique pour les bots. Veuillez mettre votre code dans un bloc de code. Si ça ne va pas, c'est bien.
Nathan Merrill
@NathanMerrill je comprends. Mais compile-t-il?
noɥʇʎԀʎzɐɹƆ
@NathanMerrill fait. Probs ne compile pas. stratégie intéressante, hein? Et une leçon d'économie!
noɥʇʎԀʎzɐɹƆ
for (offer: offers)->for (Offer offer: offers)
Nathan Merrill
corneredStockType == nulln'est pas non plus valide. un intne peut pas être null.
MegaTom
2

Spammeur, 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;
    }
}

Spam sur le marché avec des actions vraiment bon marché, et n'achetez des actions que lorsque le prix est inférieur à 20. Lorsque le nombre de stocks tombe à 1, il essaiera d'acheter n'importe quoi.

TuxCrafting
la source
fonctionne bien dans la Grande Dépression
noɥʇʎԀʎzɐɹƆ
... comment est-ce gagnant!?
noɥʇʎԀʎzɐɹƆ
2

DartMonkey, Java

(non compétitif: il ne gagnera pas et j'ai déjà une autre réponse)

Le singe Dart aime lancer des choses ... et il y a un gros tas de bâtons pointus à côté de lui. Il voit du papier sur le mur. Bam! Bam! Bam! En un rien de temps, Dart Monkey a lancé 80 fléchettes! La moitié des fléchettes sont rouges et l'autre moitié est bleue, et il y a des nombres aléatoires dessus! Dart monkey voit un ordinateur ... dart monkey tape les chiffres. Le singe Dart aime les chiffres. Dart monkey gagne de l'argent avec ses fléchettes ...


Sérieusement, DartMonkey initialise un tableau d'entiers dont la longueur est le double du nombre de stocks. Il stocke un numéro pour la quantité de stock qu'il veut acheter / vendre, et un numéro pour le prix du stock. Il alterne ensuite la vente des actions de la gamme et l'acceptation des offres en fonction de la gamme. S'il n'a pas de stock dans le tableau, il n'offrira rien, et s'il n'a aucune offre qui lui a été donnée dans le tableau, il n'acceptera rien.


Cette réponse a été inspirée par @TheNumberOne, qui a mentionné les singes fléchettes dans le chat

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;
    }

}
Phénix socratique
la source
Je vois que vous avez fait une promenade aléatoire dans Wall Street?
Rohan Jhunjhunwala
Il s'agit sans doute d'une entrée suicidaire , qui n'est pas autorisée.
Mego
1
@Mego, je ne vois pas comment ... Une entrée suicidaire vendrait des actions pour 0 dollar, cette entrée détermine ce qu'elle achète et vend au hasard. Ce qui n'est certainement pas contraire aux règles ....
Socratic Phoenix
2

InsideTrader, Java

InsideTrader a juste regardé autour de lui et a vu que tout le monde essayait d'être créatif. Mais il a fait quelque chose de créatif: faire ce qui est attendu.

Ce bot achète quand cela "en vaut la peine" car il a "emprunté" certains "documents internes" pour "guider" les "décisions d'investissement".

À faire et comment cela fonctionne dans le code. ;)

Le 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ɐɹƆ
la source
Vous ne pouvez pas avoir ces classes supplémentaires au début du fichier ... c'est syntaxiquement invalide ... elles peuvent être ajoutées à la fin sans public, je pense
Socratic Phoenix
Error on line 50: modifier private not allowed here Error on line 54: modifier private not allowed here. Je supprimerais simplement les cours et le ferais prolongerPlayer
Nathan Merrill
Juste une note, certains nouveaux bots proposent des actions à des quantités de zéro, donc votre bot lève une ArithimeticException (/ par zéro) du retour de appraiseOffer ... peut-être ajouter un chèque ou quelque chose?
Socratic Phoenix
@SocraticPhoenix Merci, corrigera.
noɥʇʎԀʎzɐɹƆ
Félicitations, ce bot est actuellement en deuxième position!
Nathan Merrill
2

WallStreet, Kotlin

Commence par vendre haut et acheter bas et passe progressivement à ce qu'il pense que le prix est vraiment. Vous pouvez également l'utiliser comme modèle pour créer le vôtre dans kotlin.

Remarque: il y a un bogue ici que je n'arrive pas à reproduire de manière fiable. Si mon programme tombe en panne ou rencontre des problèmes, veuillez me cingler dans le chat et lier une boîte à pâte du contenusubmissions/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())
    }

}
Le numéro un
la source
command.txtn'a pas besoin du nom de fichier. Belle publication!
Nathan Merrill
Je pensais que l'interpolation des chaînes avait été faite avec $ {}, pas seulement $?
Socratic Phoenix
@SocraticPhoenix $ne fonctionne qu'avec un nom de variable. ${}exécute du code arbitraire. Fondamentalement, cela fonctionne de toute façon et je préfère sans les accolades.
TheNumberOne
Pour info: en tant que solution temporaire, les utilisateurs de fenêtres qui souhaitent exécuter ce fichier doivent modifier command.txt: kotlinc-> kotlinc.batet kotlin->kotlin.bat
Nathan Merrill
Une fois que j'ai corrigé mon contrôleur, ce bot a commencé à renvoyer un tas de mauvaises données, donc je l'ai retiré de la compétition. Je peux vous aider dans la salle de chat si vous voulez :)
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) { }
}

Vendez des actions à un prix vraiment élevé et n'achetez que si le prix est inférieur à 100.

TuxCrafting
la source
1

Profiteer, Java

Le profiteur est là pour l'argent, et il compte toujours les pièces. Il fait une estimation prudente de combien d'argent il a. Il achètera alors le stock secret, s'il est inférieur à la valeur, ou achètera du stock bon marché. Il se souvient également du montant qu'il a payé pour tout et fait toujours des offres supérieures au cours de l'action. De plus, il fera des offres plus élevées s'il a moins d'argent.

Remarque: Je pense que je l'ai fait correctement, mais si @NathanMerrill ne me dérange pas d'écraser mon code pour les bogues, ce serait bien

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;
        }

    }

}
Phénix socratique
la source
vous pouvez vous endetter et toujours par actions ...
noɥʇʎԀʎzɐɹƆ
@AgentCrazyPython Je sais, mais le profiteur ne veut pas le risquer
Socratic Phoenix
ne peut pas annuler le vote
noɥʇʎԀʎzɐɹƆ
@AgentCrazyPython meh, ça va, le jeu est amusant et c'est ce qui compte
Socratic Phoenix
1

MaxBot, Java

Ce bot essaie de tirer le meilleur parti de chaque transaction. Lors de la vente, met le prix d'un stock inconnu à 300 $, lors de l'achat de 250 $.

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
la source
1

BlackMarket, Java

Pas grand chose à dire à propos de celui-ci, vu que ces transactions seront ... hors des graphiques, pourriez-vous dire.

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
la source
retour nul est à l'extérieur ... veuillez également mettre en retrait correctement.
noɥʇʎԀʎzɐɹƆ
1
@AgentCrazyPython Merci! Nous récupérerons le "return null" dès qu'il fera nuit. Méfiez-vous des voitures qui vous suivent pour le mois prochain.
Timtech
1
Pourquoi le downvote? Nous nous sommes classés quatrièmes lors de la dernière compétition. Bien que nous ne
sachions
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()

Essaie toujours de vendre des actions cachées pour plus que ce qu'il vaut.

Bleu
la source