Borsa KoTH


23

Il mercato azionario è tutto sulla velocità della conoscenza. A differenza delle precedenti sfide, l'attuale prezzo delle azioni non è casuale: è determinato da coloro che giocano. Se riesci a identificare uno stock sotto prezzo prima di chiunque altro, allora ti sei scritto un programma per fare soldi.

Il prezzo si riferisce al numero di persone che stanno negoziando le azioni, mentre Valore si riferisce all'importo che le azioni valgono alla fine del gioco.

Ogni giocatore inizia con 1000 di ogni azione e 0 patrimonio netto relativo. Ogni azione ha un valore segreto e il tuo punteggio alla fine del gioco è(stockValue for each ownedStock) + netWorth . Il tuo patrimonio netto può essere negativo. In una partita N-player, ci sono N azioni.

passi:

Il gioco segue i seguenti passi:

  1. Ti viene dato il valore segreto di un singolo titolo.
  2. Fai un'offerta per vendere azioni X di Y per $ Z
  3. Tutti i giocatori ricevono le offerte e ognuna può sceglierne una da accettare
  4. Tutti i giocatori sono informati delle offerte accettate
  5. Torna al passaggio 2

Ciascuno dei passaggi è riportato in dettaglio di seguito:

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

    • Il valore che impari non viene rivelato a nessun altro giocatore.
    • Il valore è compreso tra 0e1000
    • I valori bassi sono più simili a quelli alti (distribuzione uniforme quadrata)
  2. Offer makeOffer(List<Stock> currentStock)

    • Puoi tornare nullper non fare alcuna offerta.
  3. Offer acceptOffer(List<Offer> offers)

    • Puoi tornare nullad accettarne nessuno
    • Se non ci sono offerte disponibili, questo non verrà chiamato
    • Se accetti, il tuo patrimonio netto diminuisce di $ Z (può diventare negativo) e ricevere X di azioni Y. Il contrario si verifica con il venditore.
    • Se accetti un'offerta, lo scambio avverrà immediatamente e l'offerta verrà rimossa in modo che altri giocatori non possano accettarla.
  4. void acceptedOffers(List<Offer> offers)

    • Include anche le offerte accettate

Variabili statiche o scrittura su file non sono consentite. (Nessun dato persistente da un gioco all'altro) Sono consentiti contendenti non gravi.

interfacce:

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

Contributi non Java:

  • Tutte le chiamate sono costituiti da due linee: La prima riga è la funzione chiamata: SecretValue, MakeOffer, AcceptOffer, AcceptedOffers, SetRandom, e la seconda riga contenente i dati effettivi.
  • Le scorte sono formattati con un :delimitatore: stockType:stockAmount.
  • Le offerte sono formattate con un @delimitatore:offer@price
  • Gli elenchi sono formattati con un ;delimitatore
  • SecretValueè formattato con un :delimitatore:stockType:value
  • RandomSeedè usato per rendere deterministica la tua presentazione. Se il tuo invio utilizza la casualità, utilizza il valore intero passato come seme!
  • Tutte le chiamate di funzione richiedono una risposta. Se la risposta è nullo void, restituisce una stringa vuota.
  • Includere un command.txtche fornisce gli argomenti della riga di comando per eseguire l'invio

punteggio

Le partite composte da 1000 turni verranno eseguite più volte. I giocatori verranno segnati secondo il sistema ELO e abbinati a giocatori con livelli di abilità simili. Vince il giocatore con il punteggio ELO finale più alto! (Ho modificato il sistema in modo che ad ogni partita, i punteggi ELO vengano aggiornati per ogni accoppiamento del giocatore)

Il controller include un AutoDownloader, quindi si prega di iniziare la vostra presentazione con un colpo di testa: Name, Language. Se l'invio non è in Java, ogni blocco di codice dovrebbe iniziare con il nome del file. (escluso il file di comando, che dovrebbe essere il primo blocco nel tuo post)

In esecuzione

Esistono 2 modi per eseguire questo progetto:

  1. Scarica il codice sorgente, compila ed esegui. Puoi trovare la fonte su Github . Correregit clone --recursive https://github.com/nathanmerrill/StockExchange.git

  2. Scarica l'eseguibile JAR. Gli invii devono essere inseriti nella directory di lavoro corrente nella /submissionscartella. Puoi scaricare solo il JAR , solo gli invii o entrambi

Passa runper eseguire il progetto (opzione predefinita) o passa downloadper scaricare tutti gli invii così lontani da questa domanda.

tabellone segnapunti

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

le proprietà di magazzino non sono pubbliche, si consiglia di utilizzare i metodi getter
noɥʇʎԀʎzɐɹƆ

@AgentCrazyPython meglio?
Nathan Merrill,

i prezzi attuali sono correlati ai prezzi precedenti?
noɥʇʎԀʎzɐɹƆ

1
Una chat room sarebbe apprezzata.
TheNumberOne,

Risposte:


13

Cheater, Java

Cerca di non vendere nulla per soldi.

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

5
Ed è così che succede la grande depressione! Ho potuto vedere questo rompere un sacco di robot che acquistano a buon mercato ...
Socratic Phoenix

Congratulazioni! Ho corretto un bug critico e ora questo bot è il primo!
Nathan Merrill,

Wow, gli altri robot non sono abbastanza buoni, quindi, che questo stupido bot può vincere
solo il

8

WarGamer, Java

Dopo un esame superficiale delle regole ho deciso che la mossa vincente principale non è giocare. Chiunque offra di vendere azioni probabilmente conosce il prezzo e trarrà profitto dalla vendita. Può essere attivato in modo da fare offerte "scherzose" per vendere azioni per Integer.MAX_VALUE dollari sperando che taci e prendano i miei soldi mi morderanno.

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

1
Questo probabilmente funzionerebbe bene, tranne che mi aspetto che ci saranno voci che stupiscono leggermente più in alto. Di solito ci sono.
Geobits il

Questo non si compila.
Rainbolt,

@Rainbolt ha le dipendenze. Devi assicurarti che siano presenti.
Rohan Jhunjhunwala,

@Rainbolt quale errore del compilatore stai ricevendo
Rohan Jhunjhunwala,

1
Non sono sicuro che la parte in cui inganni l'altro
robot di

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

Accetta qualsiasi offerta.


In realtà grazie per il tuo bot
Rohan Jhunjhunwala,

6
avere +1 per rendermi ricco
Rohan Jhunjhunwala,

1
Mi sembra che ciò non sia realmente compatibile con il requisito secondo cui ogni risposta dovrebbe " essere un serio contendente per i criteri vincenti in uso ".
Peter Taylor,

2
@PeterTaylor È serio, è 5 ° in classifica
TuxCrafting

Questa è senza dubbio una voce suicida , poiché è ragionevole aspettarsi che altri robot venderanno azioni per più del loro valore, portando a te acquistare azioni per ben oltre il suo prezzo reale.
Mego,

4

DumbBot, Java

Usa questo bot per crearne uno tuo. Offre le sue scorte segrete a un prezzo scontato.

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) {
    }
}

1
Sembra che lo voglia gestire i miei soldi
Rohan Jhunjhunwala,

per favore crea questa wiki della community
noɥʇʎԀʎzɐɹƆ

@AgentCrazyPython perché?
Nathan Merrill,

@NathanMerrill rappresentante approfitta di questo manichino bot
noɥʇʎԀʎzɐɹƆ

@AgentCrazyPython Non voglio davvero che le persone lo modifichino ... Non mi interessa davvero il rappresentante, quindi sentiti libero di non votare (o votare)
Nathan Merrill

3

python_starter, Python 3

Usalo come punto di partenza per qualsiasi programma Python (o altra lingua)

Accetta un'offerta casuale.

File di comando:

python3 starter.py

Programma:

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

1
questo è troppo complicato.
noɥʇʎԀʎzɐɹƆ

2
La maggior parte è roba da aiutante. Se lo stai scrivendo in Python, devi solo implementare le 3 funzioni inferiori.
Nathan Merrill,

Che cosa fa?
noɥʇʎԀʎzɐɹƆ

Il bot accetta uno stock casuale. Il materiale ausiliario analizza / codifica, oltre a fornire classi per Offerta / Stock.
Nathan Merrill,

... e sta vincendo: /
noɥʇʎԀʎzɐɹƆ

3

VincentKasuga, Java

Non sono sicuro che il mio Java sia valido. Per favore, revisiona.

Come funziona

- se possiedi tutte le azioni, puoi impostare il prezzo delle azioni. Sei l'unico venditore. 1. Acquista tutte le azioni. 2. Impostare il prezzo di tutti gli stock in modo che sia super alto sull'ultimo tick. 3. PROFITTO! - Questo non è normalmente possibile perché ...

  • Il prezzo di solito salire alle stelle all'infinito ... ma c'è un limite!
  • ... (altri motivi per venire)

Come funziona, v2

  • Il prezzo è fissato artificialmente al massimo da alcuni stati anarchici
  • Questo è male economicamente
  • Il bot non prevede: sfrutta un difetto intrinseco nella struttura del mercato!

Fare

  • Accompagna il mercato più volte! Muahaha!

FAQ

Q: Chi è Vincent Kasuga?

A: Ha comprato tutte le cipolle e i futures sulle cipolle negli Stati Uniti. (mettili tutti in un magazzino segreto) Determina l'industria in riscatto - dammi X milioni o imposterò il prezzo alle stelle e andrai tutti in bancarotta.

Ma non si è fermato qui.

Quindi, ha segretamente messo in corto circuito l'ETF sulle cipolle (scommettendo che sarebbe sceso). Ha venduto tutte le cipolle contemporaneamente, consegnandole fisicamente in borsa a migliaia di camion. Il sacchetto di cipolla costa meno delle cipolle. Ne ha guadagnati milioni di nuovo. In breve, il fiume Hudson traboccava di cipolle.

È una persona reale.

Il codice

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

"Ho messo le spalle al mercato dell'oro, signor Bond!"


Ho incluso un downloader automatico per i robot. Si prega di inserire il codice in un blocco di codice. Se non si adatta, va bene.
Nathan Merrill,

@NathanMerrill ho capito. Ma si compila?
noɥʇʎԀʎzɐɹƆ

@NathanMerrill fatto. Probs non compilare. strategia interessante, eh? E una lezione di economia!
noɥʇʎԀʎzɐɹƆ

for (offer: offers)->for (Offer offer: offers)
Nathan Merrill il

corneredStockType == nullinoltre non è valido. un intnon può essere 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;
    }
}

Spam sul mercato con azioni davvero economiche e acquista azioni solo quando il prezzo è inferiore a 20. Quando il conteggio delle azioni scende a 1, proverà ad acquistare qualsiasi cosa.


funziona bene nella Grande Depressione
noɥʇʎԀʎzɐɹƆ

... come sta vincendo !?
noɥʇʎԀʎzɐɹƆ

2

DartMonkey, Java

(non competitivo: non vincerà e ho già un'altra risposta)

A Monkey Dart piace lanciare cose ... e c'è un grande mucchio di bastoncini appuntiti accanto a lui. Vede della carta sul muro. Bam! Bam! Bam! In pochissimo tempo, Dart Monkey ha lanciato 80 dardi! Metà delle freccette sono rosse e l'altra metà sono blu e ci sono numeri casuali su di loro! La scimmia del dardo vede un computer ... tipi di scimmia del dardo nei numeri. Alla scimmia dardo piacciono i numeri. La scimmia Dart guadagna dei soldi dalle sue freccette ...


In tutta serietà, DartMonkey inizializza un array intero che ha una lunghezza pari al doppio del numero di stock. Memorizza un numero per la quantità di azioni che desidera acquistare / vendere e un numero per il prezzo delle azioni. Quindi si alterna vendendo azioni dall'array e accettando le offerte in base all'array. Se non ha azioni dall'array, non offrirà nulla, e se non ha offerte dagli array, non accetterà nulla.


Questa risposta è stata ispirata da @TheNumberOne, che ha menzionato le scimmie dardo nella 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;
    }

}

Vedo che sei andato a fare una passeggiata casuale lungo Wall Street?
Rohan Jhunjhunwala,

Questa è probabilmente una voce suicida , che non è consentita.
Mego,

1
@Mego Non vedo come ... Una voce suicida venderebbe azioni per 0 dollari, questa voce determina ciò che acquista e vende a caso. Il che non è assolutamente contro le regole ...
Socratic Phoenix

2

InsideTrader, Java

InsideTrader si è appena guardato intorno e ha visto che tutti stavano cercando di essere creativi. Ma ha fatto qualcosa di creativo: fai ciò che è previsto.

Questo bot acquista quando "ne vale la pena" perché ha "preso in prestito" alcuni "documenti interni" per "guidare" le "decisioni di investimento".

Cose da fare e come funziona nel codice. ;)

Il codice"

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) {

    }
}

Non puoi avere queste lezioni extra all'inizio del file ... è sintatticamente non valido ... possono essere aggiunti alla fine senza pubblico, credo
Socratic Phoenix,

Error on line 50: modifier private not allowed here Error on line 54: modifier private not allowed here. Rimuoverei semplicemente le lezioni e le estendereiPlayer
Nathan Merrill,

Solo una nota, alcuni nuovi robot offrono azioni a quantità pari a zero, quindi il tuo bot sta generando un'eccezione aritimetica (/ per zero) dal ritorno di valutazioneOfferta ... forse aggiungi un assegno o qualcosa del genere?
Socratic Phoenix,

@SocraticPhoenix Grazie, risolverò.
noɥʇʎԀʎzɐɹƆ

Complimenti, questo bot è attualmente al secondo posto!
Nathan Merrill,

2

WallStreet, Kotlin

Inizia vendendo alti e acquistando bassi e si sposta gradualmente verso ciò che pensa sia davvero il prezzo. Inoltre, puoi usarlo come modello per crearne uno tuo in kotlin.

Nota: c'è un bug qui che non riesco a riprodurre in modo affidabile. Se il mio programma si arresta in modo anomalo o presenta problemi, esegui il ping in chat e collega un file bin dei contenuti disubmissions/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())
    }

}

command.txtnon è necessario il nome del file. Bel post!
Nathan Merrill,

Pensavo che l'interpolazione delle stringhe fosse stata eseguita con $ {}, non solo $?
Socratic Phoenix,

@SocraticPhoenix $funziona solo con un nome variabile. ${}esegue un codice arbitrario. Fondamentalmente, funziona in entrambi i modi e preferisco senza le parentesi graffe.
TheNumberOne

Cordiali saluti: come soluzione temporanea, gli utenti di finestre che desiderano eseguire questo file devono modificare command.txt: kotlinc-> kotlinc.bate kotlin->kotlin.bat
Nathan Merrill

Una volta risolto il mio controller, questo bot ha iniziato a restituire un sacco di dati errati, quindi l'ho rimosso dalla concorrenza. Posso aiutarti nella chat room se vuoi :)
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) { }
}

Vendi azioni a un prezzo davvero elevato e acquista solo se il prezzo è inferiore a 100.


1

Profittatore, Java

Il profitto è per i soldi e conta sempre le monete. Fa una stima prudente di quanti soldi ha. Comprerà quindi le azioni segrete, se è inferiore al valore, o acquisterà azioni economiche. Ricorda anche quanto ha pagato per tutto e fa sempre offerte al di sopra del prezzo delle azioni. Inoltre, farà offerte più alte se ha meno soldi.

Nota: penso di averlo fatto correttamente, ma se a @NathanMerrill non dispiacesse scremare il mio codice per i bug, sarebbe fantastico

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

    }

}

puoi indebitarti e ancora con le scorte ...
noɥʇʎԀʎzɐɹƆ

@AgentCrazyPython Lo so, ma il profittatore non vuole rischiare
Socratic Phoenix,

impossibile da annullare
noɥʇʎԀʎzɐɹƆ

@AgentCrazyPython meh, va bene, il gioco è divertente ed è quello che conta
Socratic Phoenix

1

MaxBot, Java

Questo bot cerca di trarre il massimo profitto da ogni transazione. Durante la vendita, il prezzo di uno stock sconosciuto a $ 300, quando si acquista $ 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;
    }
}

1

BlackMarket, Java

Non c'è molto da dire su questo, visto che queste transazioni saranno ... fuori dai grafici, potresti 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);
    }
}

return null è esterno ... per favore rientri correttamente.
noɥʇʎԀʎzɐɹƆ

1
@AgentCrazyPython Grazie! Recupereremo il "return null" non appena sarà buio. Diffidare delle auto che ti seguono per il prossimo mese.
Timtech,

1
Perché il downvote? Siamo arrivati ​​al quarto posto nell'ultima competizione. Anche se non siamo esattamente sicuri di come ...
Timtech,

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

Cerca sempre di vendere azioni nascoste per più di quanto valga la pena.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.