diff options
| author | Kostya <mail@sartin.in> | 2026-08-14 08:33:23 +0000 |
|---|---|---|
| committer | Kostya <mail@sartin.in> | 2026-08-14 08:33:23 +0000 |
| commit | 02deb7774db807f05eba4fe483de53ddd44588b2 (patch) | |
| tree | 8a358b1e038daa36eaa59f7bbba58cfe51430ef5 | |
| parent | 65ef330ad8182c95cc26260548e687d1d71c5ca2 (diff) | |
| download | guess-market-02deb7774db807f05eba4fe483de53ddd44588b2.tar.gz guess-market-02deb7774db807f05eba4fe483de53ddd44588b2.tar.xz guess-market-02deb7774db807f05eba4fe483de53ddd44588b2.zip | |
Implement LMSR mechanism and Event/Account accessors, wire EventMapperV1
Adds LmsrTradingMechanism, exposes Event/Account getters plus
Event.toEventSummary() for DTO conversion, and implements
EventMapperV1.toDomain() to build Event from the legacy XML model.
4 files changed, 176 insertions, 2 deletions
diff --git a/service/src/main/java/market/guess/service/domain/Account.java b/service/src/main/java/market/guess/service/domain/Account.java index e350400..274260e 100644 --- a/service/src/main/java/market/guess/service/domain/Account.java +++ b/service/src/main/java/market/guess/service/domain/Account.java | |||
| @@ -24,4 +24,8 @@ public final class Account { | |||
| 24 | this.balance = BigDecimalOptions.toMoney(initialBalance); | 24 | this.balance = BigDecimalOptions.toMoney(initialBalance); |
| 25 | this.clock = clock; | 25 | this.clock = clock; |
| 26 | } | 26 | } |
| 27 | |||
| 28 | public BigDecimal getBalance() { | ||
| 29 | return balance; | ||
| 30 | } | ||
| 27 | } | 31 | } |
diff --git a/service/src/main/java/market/guess/service/domain/Event.java b/service/src/main/java/market/guess/service/domain/Event.java index 4c33928..383126f 100644 --- a/service/src/main/java/market/guess/service/domain/Event.java +++ b/service/src/main/java/market/guess/service/domain/Event.java | |||
| @@ -5,6 +5,7 @@ import java.util.ArrayList; | |||
| 5 | import java.util.List; | 5 | import java.util.List; |
| 6 | import market.guess.api.CommissionTiming; | 6 | import market.guess.api.CommissionTiming; |
| 7 | import market.guess.api.EventStatus; | 7 | import market.guess.api.EventStatus; |
| 8 | import market.guess.api.EventSummaryDTO; | ||
| 8 | import market.guess.service.mechanism.TradingMechanism; | 9 | import market.guess.service.mechanism.TradingMechanism; |
| 9 | 10 | ||
| 10 | public final class Event { | 11 | public final class Event { |
| @@ -48,4 +49,98 @@ public final class Event { | |||
| 48 | this.account = new Account(AccountType.EVENT, eventKey, BigDecimalOptions.ZERO_MONEY); | 49 | this.account = new Account(AccountType.EVENT, eventKey, BigDecimalOptions.ZERO_MONEY); |
| 49 | this.status = status; | 50 | this.status = status; |
| 50 | } | 51 | } |
| 52 | |||
| 53 | public String getEventKey() { | ||
| 54 | return eventKey; | ||
| 55 | } | ||
| 56 | |||
| 57 | public int getDisplayId() { | ||
| 58 | return displayId; | ||
| 59 | } | ||
| 60 | |||
| 61 | public String getName() { | ||
| 62 | return name; | ||
| 63 | } | ||
| 64 | |||
| 65 | public String getDescription() { | ||
| 66 | return description; | ||
| 67 | } | ||
| 68 | |||
| 69 | public int getCommissionPercent() { | ||
| 70 | return commissionPercent; | ||
| 71 | } | ||
| 72 | |||
| 73 | public CommissionTiming getCommissionTiming() { | ||
| 74 | return commissionTiming; | ||
| 75 | } | ||
| 76 | |||
| 77 | public TradingMechanism getMechanism() { | ||
| 78 | return mechanism; | ||
| 79 | } | ||
| 80 | |||
| 81 | public List<Option> getOptions() { | ||
| 82 | return options; | ||
| 83 | } | ||
| 84 | |||
| 85 | public List<String> getOptionsNames() { | ||
| 86 | return options.stream().map(Option::getName).toList(); | ||
| 87 | } | ||
| 88 | |||
| 89 | public Account getAccount() { | ||
| 90 | return account; | ||
| 91 | } | ||
| 92 | |||
| 93 | public String getMarketMaker() { | ||
| 94 | return marketMaker; | ||
| 95 | } | ||
| 96 | |||
| 97 | public List<Trade> getTrades() { | ||
| 98 | return trades; | ||
| 99 | } | ||
| 100 | |||
| 101 | public EventStatus getStatus() { | ||
| 102 | return status; | ||
| 103 | } | ||
| 104 | |||
| 105 | public void setStatus(EventStatus status) { | ||
| 106 | this.status = status; | ||
| 107 | } | ||
| 108 | |||
| 109 | public String getWinningOptionKey() { | ||
| 110 | return winningOptionKey; | ||
| 111 | } | ||
| 112 | |||
| 113 | public void setWinningOptionKey(String winningOptionKey) { | ||
| 114 | this.winningOptionKey = winningOptionKey; | ||
| 115 | } | ||
| 116 | |||
| 117 | public long getNextTradeSeq() { | ||
| 118 | return nextTradeSeq; | ||
| 119 | } | ||
| 120 | |||
| 121 | public void setNextTradeSeq(long nextTradeSeq) { | ||
| 122 | this.nextTradeSeq = nextTradeSeq; | ||
| 123 | } | ||
| 124 | |||
| 125 | public BigDecimal getSettlementCommission() { | ||
| 126 | return settlementCommission; | ||
| 127 | } | ||
| 128 | |||
| 129 | public void setSettlementCommission(BigDecimal settlementCommission) { | ||
| 130 | this.settlementCommission = settlementCommission; | ||
| 131 | } | ||
| 132 | |||
| 133 | public EventSummaryDTO toEventSummary() { | ||
| 134 | return new EventSummaryDTO( | ||
| 135 | eventKey, | ||
| 136 | displayId, | ||
| 137 | name, | ||
| 138 | description, | ||
| 139 | commissionPercent, | ||
| 140 | commissionTiming, | ||
| 141 | mechanism.type(), | ||
| 142 | status, | ||
| 143 | getOptionsNames(), | ||
| 144 | account.getBalance().toPlainString()); | ||
| 145 | } | ||
| 51 | } | 146 | } |
diff --git a/service/src/main/java/market/guess/service/infrastructure/mapper/EventMapperV1.java b/service/src/main/java/market/guess/service/infrastructure/mapper/EventMapperV1.java index dadbae6..33c38e3 100644 --- a/service/src/main/java/market/guess/service/infrastructure/mapper/EventMapperV1.java +++ b/service/src/main/java/market/guess/service/infrastructure/mapper/EventMapperV1.java | |||
| @@ -1,13 +1,52 @@ | |||
| 1 | package market.guess.service.infrastructure.mapper; | 1 | package market.guess.service.infrastructure.mapper; |
| 2 | 2 | ||
| 3 | import java.util.ArrayList; | ||
| 4 | import java.util.List; | ||
| 5 | import market.guess.api.CommissionTiming; | ||
| 6 | import market.guess.api.EventStatus; | ||
| 3 | import market.guess.service.domain.Event; | 7 | import market.guess.service.domain.Event; |
| 8 | import market.guess.service.domain.Option; | ||
| 9 | import market.guess.service.mechanism.LmsrTradingMechanism; | ||
| 4 | import market.guess.service.model.v1.GMEvent; | 10 | import market.guess.service.model.v1.GMEvent; |
| 5 | 11 | ||
| 6 | public final class EventMapperV1 implements Mapper<Event, GMEvent> { | 12 | public final class EventMapperV1 implements Mapper<Event, GMEvent> { |
| 7 | 13 | ||
| 8 | @Override | 14 | @Override |
| 9 | public Event toDomain(GMEvent source) { | 15 | public Event toDomain(GMEvent source) { |
| 10 | // TODO Auto-generated method stub | 16 | return new Event( |
| 11 | throw new UnsupportedOperationException("Unimplemented method 'toDomain'"); | 17 | getEventKey(source), |
| 18 | source.getId(), | ||
| 19 | joinName(source.getName()), | ||
| 20 | source.getDescription(), | ||
| 21 | source.getComision().getValue(), | ||
| 22 | getTiming(source.getComision().getType()), | ||
| 23 | new LmsrTradingMechanism(source.getGMMethod().getGMLMSR().getB()), | ||
| 24 | EventStatus.ACTIVE, | ||
| 25 | getOptions(source), | ||
| 26 | ""); | ||
| 27 | } | ||
| 28 | |||
| 29 | private static String getEventKey(GMEvent event) { | ||
| 30 | return String.valueOf(event.getId()); | ||
| 31 | } | ||
| 32 | |||
| 33 | private static String joinName(List<String> tokens) { | ||
| 34 | return tokens == null ? "" : String.join(" ", tokens); | ||
| 35 | } | ||
| 36 | |||
| 37 | private static CommissionTiming getTiming(String type) throws IllegalArgumentException { | ||
| 38 | return switch (type) { | ||
| 39 | case "on-close" -> CommissionTiming.ON_CLOSE; | ||
| 40 | case "on-purchase" -> CommissionTiming.ON_PURCHASE; | ||
| 41 | default -> throw new IllegalArgumentException("Unknown comision type: " + type); | ||
| 42 | }; | ||
| 43 | } | ||
| 44 | |||
| 45 | private static List<Option> getOptions(GMEvent x) { | ||
| 46 | var ret = new ArrayList<Option>(x.getGMOptions().getGMOption().size()); | ||
| 47 | for (var i = 0; i < x.getGMOptions().getGMOption().size(); i++) { | ||
| 48 | ret.add(new Option(getEventKey(x) + ":" + i, x.getGMOptions().getGMOption().get(i))); | ||
| 49 | } | ||
| 50 | return ret; | ||
| 12 | } | 51 | } |
| 13 | } | 52 | } |
diff --git a/service/src/main/java/market/guess/service/mechanism/LmsrTradingMechanism.java b/service/src/main/java/market/guess/service/mechanism/LmsrTradingMechanism.java new file mode 100644 index 0000000..02a63df --- /dev/null +++ b/service/src/main/java/market/guess/service/mechanism/LmsrTradingMechanism.java | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | package market.guess.service.mechanism; | ||
| 2 | |||
| 3 | import java.math.BigDecimal; | ||
| 4 | import market.guess.api.MechanismType; | ||
| 5 | |||
| 6 | public final class LmsrTradingMechanism implements TradingMechanism { | ||
| 7 | private final int liquidity; | ||
| 8 | |||
| 9 | public LmsrTradingMechanism(int liquidity) { | ||
| 10 | super(); | ||
| 11 | this.liquidity = liquidity; | ||
| 12 | } | ||
| 13 | |||
| 14 | @Override | ||
| 15 | public MechanismType type() { | ||
| 16 | return MechanismType.LMSR; | ||
| 17 | } | ||
| 18 | |||
| 19 | @Override | ||
| 20 | public BigDecimal openingCost(int optionCount) { | ||
| 21 | // TODO Auto-generated method stub | ||
| 22 | throw new UnsupportedOperationException("Unimplemented method 'openingCost'"); | ||
| 23 | } | ||
| 24 | |||
| 25 | @Override | ||
| 26 | public BigDecimal costOfBuying(long[] q, int optionIndex, long quantity) { | ||
| 27 | // TODO Auto-generated method stub | ||
| 28 | throw new UnsupportedOperationException("Unimplemented method 'costOfBuying'"); | ||
| 29 | } | ||
| 30 | |||
| 31 | @Override | ||
| 32 | public double[] prices(long[] q) { | ||
| 33 | // TODO Auto-generated method stub | ||
| 34 | throw new UnsupportedOperationException("Unimplemented method 'prices'"); | ||
| 35 | } | ||
| 36 | } | ||