Stock Exchange KoTH


23

El mercado de valores tiene que ver con la velocidad del conocimiento. A diferencia de los desafíos anteriores, el precio actual de las acciones no es aleatorio: lo determinan quienes juegan el juego. Si puede identificar una acción de bajo precio antes que nadie, entonces ha escrito un programa para hacer dinero.

El precio se refiere a la cantidad de personas que negocian la acción, mientras que el valor se refiere a la cantidad que vale la acción al final del juego.

Cada jugador comienza con 1000 de cada acción y 0 patrimonio neto relativo. Cada acción tiene un valor secreto, y su puntaje al final del juego es(stockValue for each ownedStock) + netWorth . Su patrimonio neto puede ser negativo. En un juego de N jugadores, hay N acciones.

Pasos:

El juego sigue los siguientes pasos:

  1. Se le da el valor secreto de una sola acción.
  2. Usted hace una oferta para vender acciones X de Y por $ Z
  3. Todos los jugadores reciben las ofertas, y cada uno puede elegir uno para aceptar
  4. Todos los jugadores están informados de las ofertas aceptadas.
  5. Regrese al paso 2

Cada uno de los pasos se detalla a continuación:

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

    • El valor que aprendes no se revela a ningún otro jugador.
    • El valor es entre 0y1000
    • Es más probable que ocurran valores bajos que valores altos (distribución uniforme al cuadrado)
  2. Offer makeOffer(List<Stock> currentStock)

    • Puede regresar nullpara no hacer ninguna oferta.
  3. Offer acceptOffer(List<Offer> offers)

    • Puedes volver nulla aceptar ninguno de ellos
    • Si no hay ofertas disponibles, esto no se llamará
    • Si acepta, su patrimonio neto se reduce en $ Z (puede ser negativo) y recibe X de Y stock. Lo contrario ocurre con el vendedor.
    • Si acepta una oferta, el intercambio se realizará de inmediato, y la oferta se eliminará para que jugadores adicionales no puedan aceptarla.
  4. void acceptedOffers(List<Offer> offers)

    • Incluye sus ofertas aceptadas también

No se permiten variables estáticas o escribir en archivos. (No hay datos persistentes de un juego a otro) Se permiten contendientes no serios.

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

Envíos no Java:

  • Todas las llamadas se componen de dos líneas: La primera línea es la función de ser llamado: SecretValue, MakeOffer, AcceptOffer, AcceptedOffers, SetRandom, y la segunda línea que contiene los datos reales.
  • Las acciones están formateados con un :delimitador: stockType:stockAmount.
  • Las ofertas están formateadas con un @delimitador:offer@price
  • Las listas están formateadas con un ;delimitador
  • SecretValueestá formateado con un :delimitador:stockType:value
  • RandomSeedse utiliza para hacer su presentación determinista. Si su envío usa aleatoriedad, ¡use el valor entero pasado como semilla!
  • Todas las llamadas a funciones necesitan una respuesta. Si la respuesta es nullo void, devuelve una cadena vacía.
  • Incluya uno command.txtque proporcione los argumentos de la línea de comando para ejecutar su envío

Tanteo

Los juegos que consisten en 1000 turnos se ejecutarán varias veces. Los jugadores serán puntuados de acuerdo con el sistema ELO y emparejados con jugadores de niveles de habilidad similares. ¡El jugador con el puntaje final más alto de ELO gana! (He modificado el sistema para que cada juego, los puntajes ELO se actualicen para cada pareja de jugadores)

El controlador incluye un AutoDownloader, por lo que tiene que iniciar su presentación con un encabezado: Name, Language. Si su envío no está en Java, cada bloque de código debe comenzar con el nombre del archivo. (excluyendo el archivo de comando, que debería ser el primer bloque en su publicación)

Corriendo

Hay 2 formas de ejecutar este proyecto:

  1. Descargue el código fuente, compílelo y ejecútelo. Puedes encontrar la fuente en Github . corrergit clone --recursive https://github.com/nathanmerrill/StockExchange.git

  2. Descargue el ejecutable JAR. Las presentaciones deben colocarse en su directorio de trabajo actual en la /submissionscarpeta. Puede descargar solo el JAR , solo los envíos , o ambos

Pase runpara ejecutar el proyecto (opción predeterminada), o pase downloadpara descargar todos los envíos hasta ahora de esta pregunta.

Marcador

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

las propiedades de stock no son públicas,
indique el

@AgentCrazyPython mejor?
Nathan Merrill

¿Los precios actuales están correlacionados con los precios anteriores?
noɥʇʎԀʎzɐɹƆ

1
Se agradecería una sala de chat.
TheNumberOne

Respuestas:


13

Tramposo, Java

Intenta no vender nada por dinero.

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

55
¡Y así es como sucede la gran depresión! Pude ver esto rompiendo muchos robots que compran barato ...
Socratic Phoenix

Felicidades! Arregle un error crítico, ¡y ahora este bot está en primer lugar!
Nathan Merrill

Wow, los otros bots no son lo suficientemente buenos como para que este tonto bot pueda ganar
solo el

8

WarGamer, Java

Tras un examen superficial de las reglas, he decidido que el movimiento ganador principal no es jugar. Cualquiera que ofrezca vender acciones probablemente conozca el precio y se beneficiará de la venta. Se puede alternar para que haga ofertas de "broma" para vender una acción por Integer. MAX_VALUE dólares con la esperanza de callarse y tomar mi dinero morderán.

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
Esto probablemente funcionaría bien, excepto que espero que haya entradas que suenen un poco más altas. Por lo general hay.
Geobits

Esto no se compila.
Rainbolt

@Rainbolt tiene las dependencias. Debe asegurarse de estar presente.
Rohan Jhunjhunwala

@Rainbolt, ¿qué error del compilador está recibiendo?
Rohan Jhunjhunwala

1
No estoy seguro de que la parte en la que engañas al otro robot de broma está en el espíritu correcto ...
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;
    }
}

Acepta cualquier oferta.


De hecho, gracias por tu bot
Rohan Jhunjhunwala

66
tengo +1 por hacerme rico
Rohan Jhunjhunwala

1
Me parece que esto no es realmente compatible con el requisito de que cada respuesta debería " ser un contendiente serio para los criterios ganadores en uso ".
Peter Taylor

2
@PeterTaylor Es serio, es quinto en la tabla de clasificación
TuxCrafting

Esto podría decirse que es una entrada suicida , ya que es razonable esperar que otros bots vendan acciones por más de lo que valen, lo que lleva a comprar acciones por mucho más que su precio real.
Mego

4

DumbBot, Java

Use este bot cuando cree el suyo propio. Ofrece sus acciones secretas a un precio con descuento.

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
Parece que quiero que maneje mi dinero
Rohan Jhunjhunwala

haga esta wiki de la comunidad
noɥʇʎԀʎzɐɹƆ

@AgentCrazyPython ¿por qué?
Nathan Merrill

El representante de @NathanMerrill se beneficia de este robot ficticio
noɥʇʎԀʎzɐɹƆ

@AgentCrazyPython Realmente no quiero que la gente esté editando esto ... Realmente no me importa el representante, así que siéntete libre de no votar (o votar a favor)
Nathan Merrill

3

python_starter, Python 3

Use esto como punto de partida para cualquier programa de Python (u otro lenguaje)

Acepta una oferta aleatoria.

Archivo de comandos:

python3 starter.py

Programa:

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
Esto es muy complicado.
noɥʇʎԀʎzɐɹƆ

2
La mayor parte es ayudante. Si lo está escribiendo en python, solo necesita implementar las 3 funciones inferiores.
Nathan Merrill

¿Qué hace?
noɥʇʎԀʎzɐɹƆ

El bot acepta una acción aleatoria. El material auxiliar hace el análisis / codificación, así como también proporciona clases para Oferta / Stock.
Nathan Merrill

... y está ganando: /
noɥʇʎԀʎzɐɹƆ

3

VincentKasuga, Java

No estoy seguro si mi Java es válido. Por favor revise.

Cómo funciona

- si posee todas las acciones, puede establecer el precio de las acciones. Eres el único vendedor. 1. Compre todas las acciones. 2. Establezca el precio de todas las acciones para que sea súper alto en el último tic. 3. BENEFICIOS! - Esto normalmente no es posible porque ...

  • El precio generalmente se dispararía hasta el infinito ... ¡pero hay un límite!
  • ... (más razones para venir)

Cómo funciona, v2

  • El precio es establecido artificialmente al máximo por algún estado anarquista
  • Esto es malo económicamente
  • El bot no predice: ¡explota una falla inherente en la estructura del mercado!

Que hacer

  • ¡Acorrala el mercado varias veces! Muahaha!

Preguntas más frecuentes

P: ¿Quién es Vincent Kasuga?

R: Compró todas las cebollas y futuros de cebolla en los Estados Unidos. (ponlos a todos en un almacén secreto) Manteniendo la industria en rescate - dame X millones o fijaré el precio muy bajo y todos irán a la bancarrota.

Pero no se detuvo allí.

Luego, cortó en secreto el ETF de cebolla (apuesto a que bajaría). Vendió todas las cebollas al mismo tiempo, entregándolas físicamente en miles de camiones a la bolsa de valores. La bolsa de cebolla cuesta menos que las cebollas. Hizo millones OTRA VEZ. En resumen, el río Hudson se desbordó con cebollas.

El es una persona real.

El código

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

"¡He arrinconado el Mercado del Oro, Sr. Bond!"


He incluido un descargador automático para bots. Por favor ponga su código en un bloque de código. Si no encaja, está bien.
Nathan Merrill

@NathanMerrill lo entiendo. ¿Pero se compila?
noɥʇʎԀʎzɐɹƆ

@NathanMerrill hecho. Los problemas no se compilan. estrategia interesante, ¿eh? ¡Y una lección de economía!
noɥʇʎԀʎzɐɹƆ

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

corneredStockType == nullTampoco es válido. un intno puede ser 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;
    }
}

Envíe spam al mercado con acciones realmente baratas, y solo compre acciones cuando el precio sea inferior a 20. Cuando el recuento de acciones caiga a 1, intentará comprar cualquier cosa.


funciona bien en la Gran Depresión
noɥʇʎԀʎzɐɹƆ

... ¿Cómo está ganando esto?
noɥʇʎԀʎzɐɹƆ

2

DartMonkey, Java

(no compite: no ganará y ya tengo otra respuesta)

Al mono dardo le gusta tirar cosas ... y hay una gran pila de palos puntiagudos a su lado. Él ve algo de papel en la pared. Bam! Bam! Bam! En muy poco tiempo, ¡Dart Monkey lanzó 80 dardos! ¡La mitad de los dardos son rojos, y la otra mitad son azules, y hay números aleatorios en ellos! Dart monkey ve una computadora ... dart monkey escribe los números. Al mono dardo le gustan los números. Dart monkey gana dinero con sus dardos ...


Con toda seriedad, DartMonkey inicializa una matriz de enteros que tiene una longitud que es el doble del número de existencias. Almacena un número por la cantidad de acciones que desea comprar / vender, y un número por el precio de las acciones. Luego alterna la venta de acciones de la matriz y la aceptación de ofertas de acuerdo con la matriz. Si no tiene stock de la matriz, no ofrecerá nada, y si no tiene ofertas de la matriz, no aceptará nada.


Esta respuesta fue inspirada por @TheNumberOne, quien mencionó a los monos dardos en el 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;
    }

}

¿Veo que has ido al azar por Wall Street?
Rohan Jhunjhunwala

Podría decirse que es una entrada suicida , que no está permitida.
Mego

1
@Mego No veo cómo ... Una entrada suicida vendería acciones por 0 dólares, esta entrada determina lo que compra y vende al azar. Que definitivamente no es contra las reglas ....
socrático Phoenix

2

InsideTrader, Java

InsideTrader solo miró a su alrededor y vio que todos intentaban ser creativos. Pero hizo algo creativo: hacer lo que se espera.

Este bot compra cuando "vale la pena" porque "tomó prestados" algunos "documentos internos" para "guiar" las "decisiones de inversión".

Tareas pendientes y cómo funciona en el código. ;)

El código"

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 puede tener esas clases adicionales al comienzo del archivo ... es sintácticamente inválido ... pueden agregarse hasta el final sin público, creo
Socratic Phoenix

Error on line 50: modifier private not allowed here Error on line 54: modifier private not allowed here. Simplemente eliminaría las clases y haría que se extendieraPlayer
Nathan Merrill

Solo una nota, algunos bots nuevos están ofreciendo acciones en cantidades de cero, por lo que su bot está lanzando una ArithimeticException (/ por cero) de la devolución de appraiseOffer ... ¿tal vez agregue un cheque o algo así?
Phoenix socrático

@SocraticPhoenix Gracias, lo arreglaré.
noɥʇʎԀʎzɐɹƆ

¡Felicidades, este bot está actualmente en segundo lugar!
Nathan Merrill

2

WallStreet, Kotlin

Comienza vendiendo alto y comprando bajo y gradualmente cambia a lo que realmente cree que es el precio. Además, puede usar esto como una plantilla para hacer el suyo en kotlin.

Nota: Hay un error aquí que parece que no puedo reproducir de manera confiable. Si mi programa falla o tiene problemas, por favor envíeme un mensaje de correo electrónico en el chat y vincule un paquete de los contenidos desubmissions/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.txtNo necesita el nombre del archivo. ¡Buen post!
Nathan Merrill

Pensé que la interpolación de cadenas se realizó con $ {}, no solo $?
Phoenix socrático

@SocraticPhoenix $solo funciona con un nombre de variable. ${}ejecuta código arbitrario Básicamente, funciona de cualquier manera y prefiero sin las llaves.
TheNumberOne

FYI: como solución temporal, los usuarios de Windows que quieran ejecutar este archivo deben cambiar command.txt: kotlinc-> kotlinc.baty kotlin->kotlin.bat
Nathan Merrill el

Una vez que arreglé mi controlador, este bot comenzó a devolver un montón de datos incorrectos, así que lo eliminé de la competencia. Puedo ayudarte en la sala de chat si quieres :)
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) { }
}

Venda acciones a un precio realmente alto y solo compre si el precio es inferior a 100.


1

Profiteer, Java

El especulador está en esto por el dinero, y siempre cuenta monedas. Él hace una estimación conservadora de cuánto dinero tiene. Luego comprará las acciones secretas, si es inferior al valor, o comprará acciones baratas. También recuerda cuánto ha pagado por todo, y siempre hace ofertas por encima del precio de las acciones. Además, hará ofertas más altas si tiene menos dinero.

Nota: Creo que he hecho esto correctamente, pero si a @NathanMerrill no le importaría revisar mi código en busca de errores, sería genial

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

    }

}

puede endeudarse y aún por acciones ...
noɥʇʎԀʎzɐɹƆ

@AgentCrazyPython Lo sé, pero el especulador no quiere arriesgarse
Socratic Phoenix

no se puede cancelar la votación
noɐɹƆzɐɹƆ

@AgentCrazyPython meh, está bien, el juego es divertido y eso es lo que importa
Socratic Phoenix

1

MaxBot, Java

Este bot intenta sacar el máximo provecho de cada transacción. Al vender, pone el precio de una acción desconocida en $ 300, al comprar $ 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

No hay mucho que decir sobre este, ya que estas transacciones estarán ... fuera de los gráficos, se podría decir.

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 está afuera ... sangra correctamente también.
noɥʇʎԀʎzɐɹƆ

1
@AgentCrazyPython ¡Gracias! Recuperaremos el "retorno nulo" tan pronto como esté oscuro. Tenga cuidado con los autos que lo siguen durante el próximo mes.
Timtech

1
¿Por qué el voto negativo? Colocamos el cuarto lugar en la última competencia. Aunque no estamos exactamente seguros de cómo ...
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()

Siempre trata de vender acciones ocultas por más de lo que vale.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.