Bolsa de Valores KoTH


23

O mercado de ações tem tudo a ver com a velocidade do conhecimento. Ao contrário dos desafios anteriores, o preço atual das ações não é aleatório: é determinado por quem está jogando o jogo. Se você conseguir identificar uma ação com preço abaixo do preço antes de qualquer outra pessoa, então você mesmo escreveu um programa para ganhar dinheiro.

Preço refere-se a quanto as pessoas estão negociando as ações, enquanto Valor refere-se à quantia que as ações valem no final do jogo.

Cada jogador começa com 1000 de cada ação e 0 patrimônio líquido relativo. Cada ação tem um valor secreto, e sua pontuação no final do jogo é(stockValue for each ownedStock) + netWorth . Seu patrimônio líquido pode ser negativo. Em um jogo com N jogadores, existem N ações.

Passos:

O jogo segue os seguintes passos:

  1. Você recebe o valor secreto de uma única ação.
  2. Você faz uma oferta para vender ações X de Y por $ Z
  3. Todos os jogadores recebem as ofertas e cada um pode escolher um para aceitar
  4. Todos os jogadores são informados das ofertas aceitas
  5. Volte ao passo 2

Cada uma das etapas é fornecida em detalhes abaixo:

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

    • O valor que você aprende não é revelado a nenhum outro jogador.
    • O valor está entre 0e1000
    • Valores baixos são mais parecidos com os valores altos (distribuição uniforme ao quadrado)
  2. Offer makeOffer(List<Stock> currentStock)

    • Você pode retornar nullpara não fazer nenhuma oferta.
  3. Offer acceptOffer(List<Offer> offers)

    • Você pode voltar nulla aceitar nenhum deles
    • Se não houver ofertas disponíveis, isso não será chamado
    • Se você aceitar, seu patrimônio líquido será reduzido em $ Z (pode ficar negativo) e receberá X de ações em Y. O oposto ocorre com o vendedor.
    • Se você aceitar uma oferta, a troca ocorrerá imediatamente e a oferta será removida para que outros jogadores não possam aceitá-la.
  4. void acceptedOffers(List<Offer> offers)

    • Inclui suas ofertas aceitas também

Variáveis ​​estáticas ou gravação em arquivos não são permitidas. (Nenhum dado persistente de jogo para jogo) São permitidos candidatos não sérios.

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

Envios não Java:

  • Todas as ligações consistem em duas linhas: A primeira linha é a função a ser chamado: SecretValue, MakeOffer, AcceptOffer, AcceptedOffers, SetRandom, e a segunda linha que contém os dados reais.
  • Os estoques são formatados com um :delimitador: stockType:stockAmount.
  • As ofertas são formatadas com um @delimitador:offer@price
  • As listas são formatadas com um ;delimitador
  • SecretValueestá formatado com um :delimitador:stockType:value
  • RandomSeedé usado para tornar sua submissão determinística. Se o seu envio usar aleatoriedade, use o valor inteiro passado como a semente!
  • Todas as chamadas de função precisam de uma resposta. Se a resposta for nullou void, retorne uma sequência vazia.
  • Inclua um command.txtque forneça os argumentos da linha de comando para executar seu envio

Pontuação

Jogos com 1000 turnos serão executados várias vezes. Os jogadores serão pontuados de acordo com o sistema ELO e emparelhados com jogadores de níveis semelhantes. O jogador com a maior pontuação final no ELO vence! Modifiquei o sistema para que, a cada jogo, as pontuações no ELO sejam atualizadas para cada par de jogadores.

O controlador inclui um AutoDownloader, por isso, começar a sua apresentação com um cabeçalho: Name, Language. Se o seu envio não estiver em Java, cada bloco de código deve começar com o nome do arquivo. (excluindo o arquivo de comando, que deve ser o primeiro bloco na sua postagem)

Corrida

Existem 2 maneiras de executar este projeto:

  1. Baixe o código fonte, compile e execute. Você pode encontrar a fonte no Github . Corregit clone --recursive https://github.com/nathanmerrill/StockExchange.git

  2. Faça o download do executável JAR. Os envios devem ser colocados no seu diretório de trabalho atual na /submissionspasta Você pode fazer o download apenas do JAR , apenas dos envios ou de ambos

Passe runpara executar o projeto (opção padrão) ou faça o downloaddownload de todos os envios até agora desta pergunta.

Placar

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

as propriedades de ações não são públicas, instrua a usar métodos getter
29/08

@AgentCrazyPython melhor?
Nathan Merrill

os preços atuais estão correlacionados aos preços anteriores?
noɥʇʎԀʎzɐɹƆ

1
Uma sala de bate-papo seria apreciada.
TheNumberOne 29/08

Respostas:


13

Trapaceiro, Java

Tenta vender nada por dinheiro.

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
E é assim que a grande depressão acontece! Eu podia ver isso quebrando um monte de bots que compram barato ...
socrático Phoenix

Parabéns! Corrigi um bug crítico, e agora esse bot está em primeiro lugar!
Nathan Merrill

Wow, os outros bots não são bons o suficiente, então, que este bot mudo pode ganhar
justhalf

8

WarGamer, Java

Após um exame superficial das regras, decidi que a principal jogada vencedora é não jogar. Qualquer pessoa que ofereça venda de ações provavelmente conhece o preço e lucra com a venda. Ele pode ser alternado para oferecer ofertas de "piada" para vender uma ação por inteiro.MAX_VALUE dólares esperando calar a boca e levar meu dinheiro vai morder.

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
Provavelmente, isso funcionaria bem, exceto que espero que haja entradas com pouca sorte um pouco mais altas. Geralmente existem.
Geobits

Isso não compila.
Rainbolt 29/08/16

@Rainbolt tem as dependências. Você precisa ter certeza de que está presente.
Rohan Jhunjhunwala 29/08

@Rainbolt que erro do compilador você está recebendo
Rohan Jhunjhunwala

1
Eu não tenho certeza a parte onde você enganar o outro bot piada é no espírito certo ...
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;
    }
}

Aceita qualquer oferta.


Na verdade, obrigado por seu bot
Rohan Jhunjhunwala

6
tem +1 por me fazer rico
Rohan Jhunjhunwala

1
Parece-me que isso não é realmente compatível com a exigência de que cada resposta deve " ser um sério candidato aos critérios vencedoras em uso ".
Peter Taylor

2
@PeterTaylor É sério, é o quinto na tabela de classificação
TuxCrafting 1/16/16

É indiscutivelmente uma entrada suicida , já que é razoável esperar que outros bots vendam ações por mais do que valem, levando você a comprar ações por um preço muito superior ao seu preço real.
Mego 02/09

4

DumbBot, Java

Use este bot ao criar o seu próprio. Oferece seu estoque secreto a um preço com desconto.

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 eu quero que ele lidar com meu dinheiro
Rohan Jhunjhunwala

por favor, faça este wiki da comunidade
noɥʇʎԀʎzɐɹƆ

@AgentCrazyPython por quê?
Nathan Merrill

@NathanMerrill representante lucrando com este bot fictício
noɥʇʎԀʎzɐɹƆ

@AgentCrazyPython Eu realmente não quero que as pessoas editem isso ... Eu realmente não me importo com representante, então sinta-se livre para não fazer voto positivo (ou voto negativo) #
Nathan Merrill

3

python_starter, Python 3

Use isso como ponto de partida para qualquer programa python (ou outra linguagem)

Aceita uma oferta aleatória.

Arquivo de comando:

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
isso é muito complicado.
noɥʇʎԀʎzɐɹƆ

2
A maior parte é de material auxiliar. Se você está escrevendo em python, basta implementar as três funções inferiores.
Nathan Merrill

O que isso faz?
noɥʇʎԀʎzɐɹƆ

O bot aceita um estoque aleatório. O material auxiliar faz a análise / codificação, além de fornecer classes para Oferta / Estoque.
Nathan Merrill

... e está ganhando: /
noɥʇʎԀʎzɐɹƆ 30/08/16

3

VincentKasuga, Java

Não tenho certeza se meu Java é válido. Por favor revise.

Como funciona

- se você possui todas as ações, pode definir o preço das ações. Você é o único vendedor. 1. Compre todas as ações. 2. Defina o preço de todas as ações como super alto no último tick. 3. LUCRO! - Isso normalmente não é possível porque ...

  • O preço costuma subir rapidamente para o infinito ... mas há um limite!
  • ... (mais razões para vir)

Como funciona, v2

  • O preço é artificialmente estabelecido no máximo por algum estado anarquista
  • Isso é ruim economicamente
  • O bot não prevê - ele explora uma falha inerente na estrutura do mercado!

Façam

  • Cante o mercado várias vezes! Muahaha!

Perguntas frequentes

P: Quem é Vincent Kasuga?

A: Ele comprou todas as cebolas e futuros de cebola nos Estados Unidos. (coloque todos eles em um armazém secreto) Mantive a indústria em resgate - me dê X milhões ou vou definir o preço muito baixo e todos vocês vão à falência.

Mas ele não parou por aí.

Então, ele secretamente encurtou o ETF de cebola (apostou que ele iria cair). Ele vendeu todas as cebolas ao mesmo tempo, entregando-as fisicamente em milhares de caminhões à bolsa de valores. O saco de cebola custa menos que as cebolas. Ele fez milhões novamente. Em suma, o rio Hudson transbordou de cebola.

Ele é uma pessoa real.

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

"Eu encurralei o mercado de ouro, Sr. Bond!"


Incluí um download automático para bots. Por favor, coloque seu código em um bloco de código. Se não couber, tudo bem.
Nathan Merrill

@NathanMerrill eu entendo. Mas ele compila?
noɥʇʎԀʎzɐɹƆ

@NathanMerrill done. Probs não compila. estratégia interessante, né? E uma lição de economia!
noɥʇʎԀʎzɐɹƆ

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

corneredStockType == nulltambém não é válido. um intnão pode ser null.
MegaTom 30/08/16

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 no mercado com ações realmente baratas e só compre ações quando o preço for menor que 20. Quando a contagem de ações cair para 1, ele tentará comprar qualquer coisa.


funciona bem em Great Depression
noɥʇʎԀʎzɐɹƆ

... como isso está ganhando !?
noɥʇʎԀʎzɐɹƆ

2

DartMonkey, Java

(não concorrente: não vai ganhar e eu já tenho outra resposta)

O macaco dardo gosta de jogar coisas ... e há uma grande pilha de paus pontudos ao lado dele. Ele vê papel na parede. Bam! Bam! Bam! Em pouco tempo, o Dart Monkey lançou 80 dardos! Metade dos dardos são vermelhos, e a outra metade é azul, e há números aleatórios neles! Macaco dardo vê um computador ... digita macaco nos números. Macaco dardo gosta de números. Macaco dardo ganha dinheiro com seus dardos ...


Com toda a seriedade, o DartMonkey inicializa uma matriz inteira com um comprimento que é o dobro do número de ações. Ele armazena um número para a quantidade de ações que deseja comprar / vender e um número para o preço das ações. Ele então alterna a venda de ações da matriz e a aceitação de ofertas de acordo com a matriz. Se ele não possui ações da matriz, ele não oferece nada e, se não tiver ofertas oferecidas a ele, não aceita nada.


Esta resposta foi inspirada em @TheNumberOne, que mencionou macacos dardo no 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;
    }

}

Vejo que você saiu aleatoriamente por Wall Street?
Rohan Jhunjhunwala 31/08

Esta é sem dúvida uma entrada suicida , que não é permitida.
Mego 02/09

1
@Mego Eu não vejo como ... Uma entrada suicida venderia ações por 0 dólar, essa entrada determina o que compra e vende aleatoriamente. Que é definitivamente não é contra as regras ....
socrático Phoenix

2

InsideTrader, Java

O InsideTrader apenas olhou em volta e viu que todo mundo estava tentando ser criativo. Mas ele fez algo criativo: faça o que é esperado.

Esse bot compra quando "vale a pena", porque "emprestou" alguns "documentos internos" para "guiar" as "decisões de investimento".

Tarefas pendentes e como ele funciona no código. ;)

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

    }
}

Você não pode ter essas aulas extras no início do arquivo ... é sintaticamente inválida ... eles podem ser acrescentados ao final, sem público, eu acho
socrático Phoenix

Error on line 50: modifier private not allowed here Error on line 54: modifier private not allowed here. Gostaria apenas de remover as classes e estendê-las #Player
Nathan Merrill

Apenas uma observação, alguns novos bots estão oferecendo ações no valor de zero, então seu bot está lançando uma ArithimeticException (/ por zero) no retorno de appraiseOffer ... talvez adicione um cheque ou algo assim?
Socratic Phoenix

@SocraticPhoenix Obrigado, vai consertar.
noɥʇʎԀʎzɐɹƆ

Parabéns, este bot está atualmente em segundo!
Nathan Merrill

2

WallStreet, Kotlin

Começa vendendo alto e comprando baixo, e muda gradualmente para o que acha que realmente é o preço. Além disso, você pode usar isso como um modelo para criar o seu próprio no kotlin.

Nota: Há um erro aqui que não consigo reproduzir de maneira confiável. Se meu programa falhar ou tiver problemas, faça ping no bate - papo e vincule uma pasta do conteúdo 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.txtnão precisa do nome do arquivo. Bela postagem!
Nathan Merrill

Eu pensei que a interpolação de strings fosse feita com $ {}, não apenas $?
Phoenix socrático

@SocraticPhoenix $funciona apenas com um nome de variável. ${}executa código arbitrário. Basicamente, funciona de qualquer maneira e eu prefiro sem o aparelho.
TheNumberOne

FYI: como uma solução temporária, os usuários da janela que deseja executar essa necessidade de arquivo para mudar o command.txt: kotlinc-> kotlinc.bate kotlin->kotlin.bat
Nathan Merrill

Depois de consertar meu controlador, esse bot começou a retornar um monte de dados inválidos, então eu o removi da competição. Eu posso ajudá-lo na sala de bate-papo se você quiser :)
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 ações a um preço muito alto e compre apenas se o preço for inferior a 100.


1

Profiteer, Java

O lucro está nele pelo dinheiro, e ele está sempre contando moedas. Ele faz uma estimativa conservadora de quanto dinheiro ele tem. Ele então compra as ações secretas, se for menor que o valor, ou compra ações baratas. Ele também se lembra de quanto pagou por tudo e sempre faz ofertas acima do preço das ações. Além disso, ele fará ofertas mais altas se tiver menos dinheiro.

Nota: Acho que fiz isso corretamente, mas se o @NathanMerrill não se importasse em procurar no meu código por bugs, seria ótimo

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

    }

}

você pode entrar em dívida e ainda por ações ...
noɥʇʎԀʎzɐɹƆ

@AgentCrazyPython eu sei, mas aproveitador não quer arriscar
socrático Phoenix

não posso deixar de votar
noɥʇʎԀʎzɐɹƆ

@AgentCrazyPython meh, está tudo bem, o jogo é divertido e é isso que importa
socrático Phoenix

1

MaxBot, Java

Este bot tenta obter o máximo lucro de cada transação. Ao vender, coloca o preço de uma ação desconhecida em US $ 300, ao comprar US $ 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

Não há muito a dizer sobre este, visto que essas transações serão ... fora dos gráficos, você pode dizer.

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á fora ... por favor, identifique corretamente também.
noɥʇʎԀʎzɐɹƆ

1
@AgentCrazyPython Thanks! Recuperaremos o "retorno nulo" assim que escurecer. Desconfie de carros seguindo você no próximo mês.
Timtech 31/08/16

1
Por que o voto negativo? Ficamos em quarto lugar na última competição. Embora nós não estamos exatamente certo como ...
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()

Sempre tenta vender ações ocultas por mais do que vale a pena.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.