Bursa Efek KoTH

23

Pasar saham adalah semua tentang kecepatan pengetahuan. Tidak seperti tantangan sebelumnya, harga saham saat ini tidak acak: itu ditentukan oleh mereka yang bermain. Jika Anda dapat mengidentifikasi stok di bawah harga sebelum orang lain, maka Anda telah menulis sendiri program penghasil uang.

Harga mengacu pada berapa banyak orang memperdagangkan saham, sedangkan Nilai mengacu pada jumlah nilai saham pada akhir permainan.

Setiap pemain mulai dengan 1000 masing-masing stok, dan 0 kekayaan bersih relatif. Setiap stok memiliki nilai rahasia, dan skor Anda di akhir permainan adalah(stockValue for each ownedStock) + netWorth . Kekayaan bersih Anda bisa negatif. Dalam gim N-pemain, ada stok N.

Tangga:

Gim ini mengikuti langkah-langkah berikut:

  1. Anda diberi nilai rahasia satu saham.
  2. Anda membuat penawaran untuk menjual saham X of Y seharga $ Z
  3. Semua pemain diberi penawaran, dan masing-masing dapat memilih satu untuk menerima
  4. Semua pemain diberitahu tentang penawaran yang diterima
  5. Kembali ke langkah 2

Masing-masing langkah diberikan secara rinci di bawah ini:

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

    • Nilai yang Anda pelajari tidak diungkapkan kepada pemain lain.
    • Nilainya antara 0dan1000
    • Nilai rendah lebih suka terjadi daripada nilai tinggi (distribusi seragam kuadrat)
  2. Offer makeOffer(List<Stock> currentStock)

    • Anda dapat kembali nulluntuk tidak melakukan penawaran.
  3. Offer acceptOffer(List<Offer> offers)

    • Anda dapat kembali nulluntuk tidak menerima satupun
    • Jika tidak ada penawaran yang tersedia, ini tidak akan dipanggil
    • Jika Anda menerima, kekayaan bersih Anda turun $ Z (bisa menjadi negatif) dan menerima X saham Y. Sebaliknya terjadi pada penjual.
    • Jika Anda menerima tawaran, pertukaran akan segera terjadi, dan tawaran itu akan dihapus sehingga pemain tambahan tidak dapat menerimanya.
  4. void acceptedOffers(List<Offer> offers)

    • Termasuk penawaran yang Anda terima juga

Variabel statis atau penulisan ke file tidak diizinkan. (Tidak ada data persisten dari game ke game) Peserta yang tidak serius diizinkan.

Antarmuka:

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

Pengiriman non-Jawa:

  • Semua panggilan terdiri dari dua baris: Baris pertama adalah fungsi yang dipanggil: SecretValue, MakeOffer, AcceptOffer, AcceptedOffers, SetRandom, dan baris kedua berisi data aktual.
  • Saham diformat dengan :pembatas: stockType:stockAmount.
  • Penawaran diformat dengan @pembatas:offer@price
  • Daftar diformat dengan ;pembatas
  • SecretValuediformat dengan :pembatas:stockType:value
  • RandomSeeddigunakan untuk membuat kiriman Anda menjadi deterministik. Jika kiriman Anda menggunakan keacakan, silakan gunakan nilai integer yang diteruskan sebagai seed!
  • Semua panggilan fungsi perlu ditanggapi. Jika responsnya adalah nullatau void, kembalikan string kosong.
  • Harap sertakan command.txtargumen baris perintah yang diberikan untuk menjalankan kiriman Anda

Mencetak gol

Game yang terdiri dari 1000 putaran akan dijalankan beberapa kali. Pemain akan diberi skor sesuai dengan sistem ELO , dan dipasangkan dengan pemain dengan tingkat keterampilan yang sama. Pemain dengan skor ELO akhir tertinggi menang! (Saya telah memodifikasi sistem sehingga setiap pertandingan, skor ELO diperbarui untuk setiap pasangan pemain)

Controller mencakup AutoDownloader, jadi silakan mulai kiriman Anda dengan sebuah sundulan: Name, Language. Jika kiriman Anda tidak di Jawa, setiap blok kode harus dimulai dengan nama file. (tidak termasuk file perintah, yang seharusnya menjadi blok pertama di posting Anda)

Lari

Ada 2 cara untuk menjalankan proyek ini:

  1. Unduh kode sumber, kompilasi dan jalankan. Anda dapat menemukan sumbernya di Github . Menjalankangit clone --recursive https://github.com/nathanmerrill/StockExchange.git

  2. Unduh eksekusi JAR. Pengajuan harus ditempatkan di direktori kerja Anda saat ini di /submissionsfolder. Anda dapat mengunduh hanya JAR , hanya pengiriman , atau keduanya

Lewati rununtuk menjalankan proyek (opsi default), atau lewati downloaduntuk mengunduh semua kiriman sejauh ini dari pertanyaan ini.

Papan angka

1.  1308.1220497323848  Cheater
2.  1242.0333695640356  InsideTrader
3.  1158.3662658295411  UncleScrooge
4.  1113.8344000358493  BlackMarket
5.  1051.8370015258993  DartMonkey
6.  983.0545446731494   WarGamer
7.  939.457423938002    Spammer
8.  901.4372529538886   DumbBot
9.  859.0519326039137   ShutUpAndTakeMyMoney
10. 852.9448222849587   VincentKasuga
11. 718.2112067329083   Profiteer
Nathan Merrill
sumber
properti saham tidak umum, diinstruksikan untuk menggunakan metode pengambil
noɥʇʎԀʎzɐɹƆ
@ AgentCrazyPython lebih baik?
Nathan Merrill
Apakah harga saat ini berkorelasi dengan harga sebelumnya?
noɥʇʎԀʎzɐɹƆ
1
Ruang obrolan akan dihargai.
TheNumberOne

Jawaban:

13

Penipu, Jawa

Berusaha tidak menjual apa pun demi uang.

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

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

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

    public Offer makeOffer(List<Stock> currentStock){
        Stock stock = randomStock();
        int price = random.nextInt(100) + 1;
        return new Offer(stock.setAmount(0), price);
    }
}
CommonGuy
sumber
5
Dan itulah bagaimana depresi hebat terjadi! Saya bisa melihat ini melanggar banyak bot yang membeli murah ...
Socratic Phoenix
Selamat! Saya memperbaiki bug penting, dan sekarang bot ini ada di dalam!
Nathan Merrill
Wow, bot yang lain tidak cukup bagus, sehingga bot bodoh ini bisa menang
justhalf
8

WarGamer, Jawa

Setelah pemeriksaan asal-asalan aturan saya telah memutuskan bahwa langkah kemenangan utama adalah tidak bermain. Siapa pun yang menawarkan untuk menjual saham kemungkinan tahu harga dan akan mendapat untung dari penjualan. Ini dapat diaktifkan sehingga akan membuat "lelucon" penawaran untuk menjual saham untuk Integer.MAX_VALUE dolar berharap tutup mulut dan mengambil uang saya akan menggigit.

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

import java.util.List;

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

    public Offer makeOffer(List<Stock> currentStock){
    if(FRAUD)
    return new Offer(new Stock(0,1),Integer.MAX_VALUE);
        //defraud shut up and take my money            
    return null;
    }
}
Rohan Jhunjhunwala
sumber
1
Ini mungkin akan bekerja dengan baik, kecuali saya berharap akan ada entri yang bodoh-keberuntungan dengan cara mereka sedikit lebih tinggi. Biasanya ada.
Geobits
Ini tidak dikompilasi.
Rainbolt
@ Rainain memiliki dependensi. Anda harus memastikan ada.
Rohan Jhunjhunwala
@Rainbolt kesalahan kompiler apa yang Anda dapatkan
Rohan Jhunjhunwala
1
Saya tidak yakin bagian di mana Anda menipu bot lelucon lainnya dalam semangat yang tepat ...
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;
    }
}

Ia menerima tawaran apa pun.

TuxCrafting
sumber
Sebenarnya terima kasih untuk bot Anda
Rohan Jhunjhunwala
6
punya +1 untuk membuat saya kaya
Rohan Jhunjhunwala
1
Tampaknya bagi saya ini tidak benar-benar cocok dengan persyaratan bahwa setiap jawaban harus " menjadi penantang serius untuk kriteria pemenang yang digunakan ".
Peter Taylor
2
@PeterTaylor Serius, ini nomor 5 di papan peringkat
TuxCrafting
Ini bisa dibilang entri bunuh diri , karena masuk akal untuk berharap bahwa bot lain akan menjual saham lebih dari nilainya, membuat Anda membeli saham lebih dari harga sebenarnya.
Mego
4

DumbBot, Java

Gunakan bot ini saat membuat bot Anda sendiri. Menawarkan saham rahasianya dengan harga diskon.

import java.util.List;
import com.ppcg.stockexchange.*;
public class DumbBot extends Player {
    public Offer acceptOffer(List<Offer> offers) {
        return null;
    }
    public Offer makeOffer(List<Stock> currentStock){
        return new Offer(currentStock.get(secretStockType).setAmount(1), Math.max(1, secretStockValue - 5));
    }
    public void secretValue(int stockType, int value) {
        super.secretValue(stockType, value);
    }
    public void acceptedOffers(List<Offer> acceptedOffers) {
    }
}
Nathan Merrill
sumber
1
Sepertinya saya ingin dia menangani uang saya
Rohan Jhunjhunwala
tolong buat komunitas ini wiki
noɥʇʎԀʎzɐɹƆ
@ AgentCrazyPython mengapa?
Nathan Merrill
@NathanMerrill perwakilan yang mendapat untung dari bot dummy ini
noɥʇʎԀʎzɐɹƆ
@AgentCrazyPython Saya tidak benar-benar ingin orang mengedit ini ... Saya tidak benar-benar peduli tentang perwakilan, jadi jangan ragu untuk tidak mengungguli (atau downvote)
Nathan Merrill
3

python_starter, Python 3

Gunakan ini sebagai titik awal untuk program python (atau bahasa lain) apa pun

Menerima tawaran acak.

File perintah:

python3 starter.py

Program:

starter.py
import random
from functools import total_ordering


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


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

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

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

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

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

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

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

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

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

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


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

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

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


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


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


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


def start():
    while True:
        process_input()


hidden_stock = None
hidden_price = None


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


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


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


if __name__ == "__main__":
    start()
Nathan Merrill
sumber
1
ini terlalu rumit.
noɥʇʎԀʎzɐɹƆ
2
Sebagian besar adalah hal-hal pembantu. Jika Anda menulisnya dengan python, Anda hanya perlu mengimplementasikan 3 fungsi terbawah.
Nathan Merrill
apa fungsinya?
noɥʇʎԀʎzɐɹƆ
Bot menerima stok acak. Barang-barang pembantu tidak parsing / encoding, serta menyediakan kelas untuk Penawaran / Stok.
Nathan Merrill
... dan ia menang: /
noɥʇʎԀʎzɐɹƆ
3

Vincent Kasuga, Jawa

Tidak yakin apakah Java saya valid. Silakan tinjau.

Bagaimana itu bekerja

- jika Anda memiliki semua stok, Anda dapat mengatur harga stok. Anda adalah satu-satunya penjual. 1. Beli semua persediaan. 2. Tetapkan harga semua saham menjadi super tinggi pada tick terakhir. 3. KEUNTUNGAN! - Ini biasanya tidak mungkin karena ...

  • Harganya biasanya akan meroket hingga tak terbatas ... tapi ada batasnya!
  • ... (lebih banyak alasan untuk datang)

Cara kerjanya, v2

  • Harga ditentukan secara maksimum oleh beberapa negara anarkis
  • Ini buruk secara ekonomi
  • Bot tidak memprediksi - ia mengeksploitasi cacat bawaan dalam struktur pasar!

Melakukan

  • Pojok pasar beberapa kali! Muahaha!

Faq

T: Siapa Vincent Kasuga?

A: Dia membeli semua bawang dan berjangka bawang di Amerika Serikat. (menempatkan mereka semua di gudang rahasia) Mengadakan industri tebusan - beri saya X juta atau saya akan menetapkan harga rendah dan Anda semua akan bangkrut.

Tapi dia tidak berhenti di situ.

Kemudian, dia diam-diam menyingkat bawang ETF (bertaruh bahwa itu akan turun). Dia menjual semua bawang pada satu waktu, secara fisik mengirimkannya dalam ribuan truk ke bursa. Tas bawang lebih murah dari bawang. Dia menghasilkan jutaan LAGI. Singkatnya, sungai Hudson dipenuhi bawang.

Dia orang yang nyata.

Kode

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

"Saya sudah memojokkan Pasar Emas, Tuan Bond!"

noɥʇʎԀʎzɐɹƆ
sumber
Saya telah menyertakan pengunduh otomatis untuk bot. Silakan masukkan kode Anda di blok-kode. Jika tidak cocok, itu tidak masalah.
Nathan Merrill
@NathanMerrill, saya mengerti. Tetapi apakah itu dikompilasi?
noɥʇʎԀʎzɐɹƆ
@NathanMerrill selesai. Probs tidak dikompilasi. strategi yang menarik, eh? Dan pelajaran di bidang ekonomi!
noɥʇʎԀʎzɐɹƆ
for (offer: offers)->for (Offer offer: offers)
Nathan Merrill
corneredStockType == nulljuga tidak valid. sebuah inttidak bisa 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 pasar dengan stok benar-benar murah, dan hanya membeli saham ketika harganya kurang dari 20. Ketika jumlah stok jatuh ke 1, itu akan mencoba membeli apa pun.

TuxCrafting
sumber
bekerja dengan baik di Depresi Hebat
noɥʇʎԀʎzɐɹƆ
... bagaimana kemenangan ini !?
noɥʇʎԀʎzɐɹƆ
2

DartMonkey, Java

(non-bersaing: Tidak akan menang dan saya sudah punya jawaban lain)

Monyet Dart suka melempar barang-barang ... dan ada tumpukan besar tongkat runcing di sebelahnya. Dia melihat beberapa kertas di dinding. Bam! Bam! Bam! Dalam waktu singkat, Dart Monkey melempar 80 anak panah! Setengah anak panah berwarna merah, dan setengah lainnya berwarna biru, dan ada angka acak di sana! Monyet dart melihat komputer ... jenis monyet dart dalam angka. Monyet Dart suka angka. Monyet dart menghasilkan uang dari anak panahnya ...


Dalam keseriusan semua, DartMonkey menginisialisasi array integer yang memiliki panjang dua kali jumlah saham. Dia menyimpan satu nomor untuk jumlah stok yang ingin dia beli / jual, dan satu nomor untuk harga saham. Dia kemudian berganti-ganti menjual saham dari array, dan menerima penawaran sesuai dengan array. Jika dia tidak memiliki stok dari array, dia tidak akan menawarkan apa pun, dan jika dia tidak memiliki penawaran yang diberikan kepadanya dari array, dia tidak akan menerima apa pun.


Jawaban ini terinspirasi oleh @TheNumberOne, yang menyebutkan monyet panah dalam obrolan

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

}
Phoenix Sokrates
sumber
Saya melihat Anda telah berjalan secara acak di jalan tembok?
Rohan Jhunjhunwala
Ini bisa dibilang entri bunuh diri , yang tidak diizinkan.
Mego
1
@Mego Saya tidak melihat bagaimana ... Entri bunuh diri akan menjual saham untuk 0 dolar, entri ini menentukan apa yang dibeli dan dijual secara acak. Yang pasti tidak melanggar aturan ....
Socratic Phoenix
2

InsideTrader, Java

InsideTrader hanya melihat sekeliling dan melihat bahwa semua orang berusaha untuk menjadi kreatif. Tapi dia melakukan sesuatu yang kreatif: melakukan apa yang diharapkan.

Bot ini dibeli ketika "layak" karena "meminjam" beberapa "dokumen internal" untuk "membimbing" "keputusan investasi".

Agenda dan cara kerjanya dalam kode. ;)

Kode"

import java.util.List;

import com.ppcg.stockexchange.*;

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

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

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

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

    public void acceptedOffers(List<Offer> acceptedOffers) {

    }
}
noɥʇʎԀʎzɐɹƆ
sumber
Anda tidak dapat memiliki kelas tambahan di awal file ... secara sintaksis tidak valid ... mereka dapat ditambahkan sampai akhir tanpa publik, saya pikir
Socratic Phoenix
Error on line 50: modifier private not allowed here Error on line 54: modifier private not allowed here. Saya baru saja menghapus kelas, dan memperpanjangnyaPlayer
Nathan Merrill
Sekedar catatan, beberapa bot baru menawarkan saham dalam jumlah nol, jadi bot Anda melempar ArithimeticException (/ dengan nol) dari kembalinya appraiseOffer ... mungkin menambahkan cek atau sesuatu?
Socratic Phoenix
@ SocratesPhoenix Terima kasih, akan diperbaiki.
noɥʇʎԀʎzɐɹƆ
Selamat, bot ini saat ini berada di urutan kedua!
Nathan Merrill
2

WallStreet, Kotlin

Mulai dengan menjual tinggi dan membeli rendah dan secara bertahap bergeser ke apa yang menurutnya harga sebenarnya. Anda juga dapat menggunakan ini sebagai templat untuk membuatnya di kotlin.

Catatan: Ada bug di sini yang sepertinya tidak bisa saya reproduksi dengan benar. Jika program saya mogok atau mengalami masalah, harap ping saya dalam obrolan dan tautkan pastebin dari kontensubmissions/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())
    }

}
TheNumberOne
sumber
command.txttidak perlu nama file. Pos yang bagus!
Nathan Merrill
Saya pikir interpolasi string dilakukan dengan $ {}, bukan hanya $?
Socratic Phoenix
@ SocratesPhoenix $hanya berfungsi dengan nama variabel. ${}mengeksekusi kode arbitrer. Pada dasarnya, ini bekerja dengan baik dan saya lebih suka tanpa kawat gigi.
TheNumberOne
FYI: sebagai solusi sementara, pengguna jendela yang ingin menjalankan file ini perlu mengubah command.txt: kotlinc-> kotlinc.batdan kotlin->kotlin.bat
Nathan Merrill
Setelah saya memperbaiki pengontrol saya, bot ini mulai mengembalikan banyak data buruk, jadi saya menghapusnya dari kompetisi. Saya dapat membantu Anda di ruang obrolan jika Anda mau :)
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) { }
}

Jual stok dengan harga sangat tinggi, dan hanya beli jika harganya kurang dari 100.

TuxCrafting
sumber
1

Pencatut, Jawa

Untung ada di dalamnya untuk uang, dan dia selalu menghitung koin. Dia membuat perkiraan konservatif tentang berapa banyak uang yang dia dapatkan. Dia kemudian akan membeli saham rahasia, jika nilainya di bawah nilainya, atau membeli saham murah. Dia juga ingat berapa banyak yang dia bayar untuk semuanya, dan selalu membuat penawaran di atas harga saham. Selain itu, dia akan membuat penawaran lebih tinggi jika dia memiliki uang lebih sedikit.

Catatan: Saya pikir saya sudah melakukan ini dengan benar, tetapi jika @NathanMerrill tidak keberatan membaca kode saya untuk bug, itu akan menjadi luar biasa

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

    }

}
Phoenix Sokrates
sumber
Anda bisa berhutang dan masih dengan saham ...
noɥʇʎԀʎzɐɹƆ
@ AgentCrazyPython Saya tahu, tetapi pencatut tidak mau mengambil risiko
Socratic Phoenix
tidak dapat undownvote
noɥʇʎԀʎzɐɹƆ
@AgentCrazyPython meh, tidak apa-apa, permainan ini menyenangkan dan itulah yang penting
Socratic Phoenix
1

MaxBot, Java

Bot ini mencoba menghasilkan keuntungan maksimal dari setiap transaksi Saat menjual, masukkan harga saham yang tidak dikenal pada $ 300, saat membeli $ 250.

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

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

BlackMarket, Jawa

Tidak banyak bicara tentang ini, mengingat transaksi ini akan ... dari grafik, Anda mungkin mengatakan.

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

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

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

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


    public Offer makeOffer(List<Stock> currentStock) {
        return new Offer(new Stock(0,1),420);
    }
}
Timtech
sumber
return null ada di luar ... harap indentasi dengan benar juga.
noɥʇʎԀʎzɐɹƆ
1
@AgentCrazyPython Terima kasih! Kami akan mengambil "return null" segera setelah gelap. Berhati-hatilah dengan mobil yang mengikutimu untuk bulan berikutnya.
Timtech
1
Mengapa downvote? Kami menempati posisi keempat dalam kompetisi terakhir. Meskipun kami tidak yakin bagaimana ...
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()

Selalu mencoba untuk menjual saham tersembunyi lebih dari nilainya.

Biru
sumber