be-components 6.2.1 → 6.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/lib/commonjs/Competition/components/CompetitionPlay.js +8 -1
  2. package/lib/commonjs/Competition/components/CompetitionPlay.js.map +1 -1
  3. package/lib/commonjs/Competition/components/MarketsCard.js +1 -0
  4. package/lib/commonjs/Competition/components/MarketsCard.js.map +1 -1
  5. package/lib/commonjs/Components/Icons.js +49 -0
  6. package/lib/commonjs/Components/Icons.js.map +1 -1
  7. package/lib/commonjs/MarketComponents/api/index.js +189 -0
  8. package/lib/commonjs/MarketComponents/api/index.js.map +1 -1
  9. package/lib/commonjs/MarketComponents/components/CreateMarketForm.js +736 -0
  10. package/lib/commonjs/MarketComponents/components/CreateMarketForm.js.map +1 -0
  11. package/lib/commonjs/MarketComponents/components/WeightProgress.js +53 -0
  12. package/lib/commonjs/MarketComponents/components/WeightProgress.js.map +1 -0
  13. package/lib/commonjs/MarketComponents/index.js +2 -0
  14. package/lib/commonjs/MarketComponents/index.js.map +1 -1
  15. package/lib/commonjs/MarketMaker/api/index.js +3 -0
  16. package/lib/commonjs/MarketMaker/api/index.js.map +1 -1
  17. package/lib/commonjs/Poll/components/PollCard.js +3 -0
  18. package/lib/commonjs/Poll/components/PollCard.js.map +1 -1
  19. package/lib/module/Competition/components/CompetitionPlay.js +8 -1
  20. package/lib/module/Competition/components/CompetitionPlay.js.map +1 -1
  21. package/lib/module/Competition/components/MarketsCard.js +1 -0
  22. package/lib/module/Competition/components/MarketsCard.js.map +1 -1
  23. package/lib/module/Components/Icons.js +49 -0
  24. package/lib/module/Components/Icons.js.map +1 -1
  25. package/lib/module/MarketComponents/api/index.js +189 -0
  26. package/lib/module/MarketComponents/api/index.js.map +1 -1
  27. package/lib/module/MarketComponents/components/CreateMarketForm.js +727 -0
  28. package/lib/module/MarketComponents/components/CreateMarketForm.js.map +1 -0
  29. package/lib/module/MarketComponents/components/WeightProgress.js +45 -0
  30. package/lib/module/MarketComponents/components/WeightProgress.js.map +1 -0
  31. package/lib/module/MarketComponents/index.js +2 -0
  32. package/lib/module/MarketComponents/index.js.map +1 -1
  33. package/lib/module/MarketMaker/api/index.js +3 -0
  34. package/lib/module/MarketMaker/api/index.js.map +1 -1
  35. package/lib/module/Poll/components/PollCard.js +3 -0
  36. package/lib/module/Poll/components/PollCard.js.map +1 -1
  37. package/lib/typescript/lib/commonjs/Competition/components/CompetitionPlay.d.ts.map +1 -1
  38. package/lib/typescript/lib/commonjs/Competition/components/MarketsCard.d.ts.map +1 -1
  39. package/lib/typescript/lib/commonjs/Components/Icons.d.ts +10 -0
  40. package/lib/typescript/lib/commonjs/Components/Icons.d.ts.map +1 -1
  41. package/lib/typescript/lib/commonjs/MarketComponents/api/index.d.ts +6 -0
  42. package/lib/typescript/lib/commonjs/MarketComponents/api/index.d.ts.map +1 -1
  43. package/lib/typescript/lib/commonjs/MarketComponents/components/CreateMarketForm.d.ts +20 -0
  44. package/lib/typescript/lib/commonjs/MarketComponents/components/CreateMarketForm.d.ts.map +1 -0
  45. package/lib/typescript/lib/commonjs/MarketComponents/components/WeightProgress.d.ts +8 -0
  46. package/lib/typescript/lib/commonjs/MarketComponents/components/WeightProgress.d.ts.map +1 -0
  47. package/lib/typescript/lib/commonjs/MarketComponents/index.d.ts +1 -0
  48. package/lib/typescript/lib/commonjs/MarketMaker/api/index.d.ts.map +1 -1
  49. package/lib/typescript/lib/commonjs/Poll/components/PollCard.d.ts.map +1 -1
  50. package/lib/typescript/lib/module/Competition/components/CompetitionPlay.d.ts.map +1 -1
  51. package/lib/typescript/lib/module/Competition/components/MarketsCard.d.ts.map +1 -1
  52. package/lib/typescript/lib/module/Components/Icons.d.ts +10 -0
  53. package/lib/typescript/lib/module/Components/Icons.d.ts.map +1 -1
  54. package/lib/typescript/lib/module/MarketComponents/api/index.d.ts +6 -0
  55. package/lib/typescript/lib/module/MarketComponents/api/index.d.ts.map +1 -1
  56. package/lib/typescript/lib/module/MarketComponents/components/CreateMarketForm.d.ts +20 -0
  57. package/lib/typescript/lib/module/MarketComponents/components/CreateMarketForm.d.ts.map +1 -0
  58. package/lib/typescript/lib/module/MarketComponents/components/WeightProgress.d.ts +8 -0
  59. package/lib/typescript/lib/module/MarketComponents/components/WeightProgress.d.ts.map +1 -0
  60. package/lib/typescript/lib/module/MarketComponents/index.d.ts +2 -0
  61. package/lib/typescript/lib/module/MarketComponents/index.d.ts.map +1 -1
  62. package/lib/typescript/lib/module/MarketMaker/api/index.d.ts.map +1 -1
  63. package/lib/typescript/lib/module/Poll/components/PollCard.d.ts.map +1 -1
  64. package/lib/typescript/src/Competition/components/MarketsCard.d.ts.map +1 -1
  65. package/lib/typescript/src/Components/Icons.d.ts +2 -0
  66. package/lib/typescript/src/Components/Icons.d.ts.map +1 -1
  67. package/lib/typescript/src/MarketComponents/api/index.d.ts +6 -0
  68. package/lib/typescript/src/MarketComponents/api/index.d.ts.map +1 -1
  69. package/lib/typescript/src/MarketComponents/components/CreateMarketForm.d.ts +27 -0
  70. package/lib/typescript/src/MarketComponents/components/CreateMarketForm.d.ts.map +1 -0
  71. package/lib/typescript/src/MarketComponents/components/WeightProgress.d.ts +12 -0
  72. package/lib/typescript/src/MarketComponents/components/WeightProgress.d.ts.map +1 -0
  73. package/lib/typescript/src/MarketComponents/index.d.ts +21 -0
  74. package/lib/typescript/src/MarketComponents/index.d.ts.map +1 -1
  75. package/lib/typescript/src/MarketMaker/api/index.d.ts +1 -1
  76. package/lib/typescript/src/MarketMaker/api/index.d.ts.map +1 -1
  77. package/lib/typescript/src/Poll/components/PollCard.d.ts.map +1 -1
  78. package/package.json +1 -1
  79. package/src/Competition/components/CompetitionPlay.tsx +6 -6
  80. package/src/Competition/components/MarketsCard.tsx +1 -0
  81. package/src/Components/Icons.tsx +26 -0
  82. package/src/MarketComponents/api/index.ts +166 -3
  83. package/src/MarketComponents/components/CreateMarketForm.tsx +444 -0
  84. package/src/MarketComponents/components/WeightProgress.tsx +32 -0
  85. package/src/MarketComponents/index.tsx +2 -0
  86. package/src/MarketMaker/api/index.ts +2 -1
  87. package/src/Poll/components/PollCard.tsx +1 -0
@@ -1,7 +1,8 @@
1
1
  import axios from 'axios';
2
2
  import { APIOverrides } from "../../ApiOverrides"
3
3
  import type { AthleteProps, AthleteStatProps, BestAvailableOrderProps, BestAvailableResponseProps, ContestStatProps, EventOrderStatProps, EventProps, ExternalPriceProps, LeagueProps, MarketProps, MarketSideOptionProps, MarketStatsProps, MatchProps, MyPlayerProps, OrderProps, PodcastProps, PositionProps, PublicPlayerProps, TeamProps, TournamentProps, TradeProps } from "../../types"
4
- import moment from 'moment-mini';
4
+ import moment, { type Moment } from 'moment-mini';
5
+ import { MarketMaketHelpers } from '../../MarketMaker/api';
5
6
 
6
7
  let EVENT_SVC_API = ''
7
8
  let AUTH_SVC_API = ''
@@ -526,6 +527,21 @@ const MarketComponentHelpers = {
526
527
  }
527
528
  return (p/(1-(p/100)))*-1
528
529
  },
530
+ getSideIds: (contest_type:string, so:MarketSideOptionProps, market?:MarketProps, event?:EventProps, tournament?:TournamentProps, match?:MatchProps, athlete?:AthleteProps, team?:TeamProps) => {
531
+ if(!market){ return undefined }
532
+ switch(contest_type){
533
+ case 'team':
534
+ if(!event) return undefined
535
+ return MarketComponentHelpers.getTeamEventSideIds(event, market, so, athlete, team)
536
+ case 'tournament':
537
+ if(!tournament){ return undefined }
538
+ return MarketComponentHelpers.getTournamentSideIds(market, so, athlete, team);
539
+ case 'match':
540
+ if(!match){ return undefined }
541
+ return MarketComponentHelpers.getMatchSideIds(match, so)
542
+ default: return undefined
543
+ }
544
+ },
529
545
  getTournamentSideIds: (market:MarketProps, side_option:MarketSideOptionProps, athlete?:AthleteProps, team?:TeamProps) => {
530
546
  const o_side = market.side_options.find(so => so.side != side_option.side);
531
547
  if(!o_side){ return undefined }
@@ -544,6 +560,46 @@ const MarketComponentHelpers = {
544
560
  default: return undefined
545
561
  }
546
562
  },
563
+ pretendFulfillOrder: (order:BestAvailableOrderProps | OrderProps, stake?:number):OrderProps => {
564
+ let fill_stake = stake ?? order.open_amt
565
+ if(fill_stake > order.open_amt){
566
+ fill_stake = order.open_amt
567
+ }
568
+ order.open_amt -= fill_stake
569
+ order.called_amt = fill_stake
570
+
571
+ let position:PositionProps = {
572
+ position_id: '',
573
+ order_id: order.order_id,
574
+ stake: fill_stake,
575
+ probability: order.probability,
576
+ odds: order.odds,
577
+ status: 'inprogress',
578
+ winnings: 0, net_winnings: 0,
579
+ potential_winnings: MarketComponentHelpers.calcPotentialWinnings(fill_stake, order.odds),
580
+ original_stake: fill_stake,
581
+ cash_rcvd: 0,
582
+ delayed_cash: 0,
583
+ in_sale_order: 0,
584
+ commission: 0
585
+ }
586
+ return {
587
+ ...order,
588
+ be_type: 'market',
589
+ order_type:'limit',
590
+ collar_pct: 0,
591
+ position_ids: [],
592
+ market_type: 'FOR_MONEY',
593
+ status: 'approved',
594
+ available_for_parlays:false,
595
+ resolution_status: 'inprogress',
596
+ commission_pct: 0,
597
+ side_type: order.side_type as 'team'|'side'|'athlete',
598
+ buy_sell_ind: order.buy_sell_ind as 'buy'|'sell',
599
+ event_type: order.event_type as 'team'|'tournament'|'match',
600
+ positions: [position]
601
+ }
602
+ },
547
603
  prettyKey : (key?:string) => {
548
604
  try {
549
605
  if(!key){ return '' }
@@ -751,6 +807,113 @@ const MarketComponentHelpers = {
751
807
  }
752
808
  })
753
809
  return { contest_title, o_side_label, trade_side_label }
754
-
755
- }
810
+ },
811
+ setMarket: (unit_size:number, contest_type:'team'|'tournament'|'match',best_available:BestAvailableOrderProps[], external_prices:ExternalPriceProps[], o_side_margin:number, trade_side_margin:number, market?:MarketProps, event?:EventProps, tournament?:TournamentProps, match?:MatchProps, athlete?:AthleteProps, team?:TeamProps) => {
812
+ let orders:OrderProps[] = []
813
+ let expire_datetime:Moment | undefined = undefined
814
+ if(!market){ return [] }
815
+ market.side_options.map(so => {
816
+ let side_id_response:any = undefined
817
+ switch(contest_type){
818
+ case 'team':
819
+ if(!event){ return }
820
+ expire_datetime = moment(event.scheduled_datetime);
821
+ side_id_response = MarketComponentHelpers.getTeamEventSideIds(event, market, so);
822
+ break
823
+ case 'tournament':
824
+ if(!tournament){ return }
825
+ expire_datetime = moment(tournament.scheduled_datetime);
826
+ side_id_response = MarketComponentHelpers.getTournamentSideIds(market, so, athlete, team);
827
+ break
828
+ case 'match':
829
+ if(!match){ return }
830
+ expire_datetime = moment(match.scheduled_datetime);
831
+ side_id_response = MarketComponentHelpers.getMatchSideIds(match, so);
832
+ break
833
+ default: return
834
+ }
835
+
836
+ if(!side_id_response){ return }
837
+ let ba = best_available.find(ba => ba.side == so.side)
838
+ let o_ba = best_available.find(ba => ba.side != so.side);
839
+ if(ba && o_ba){
840
+ let ba_trade = MarketMaketHelpers.getTradeFromAvailableOrder(ba, side_id_response.reversed_side_id);
841
+ let ba_order = MarketMaketHelpers.getOrderFromTrade(ba_trade, 10, ba.order_id);
842
+ let ba_title = MarketComponentHelpers.getOrderTitle(ba_order, market, event, tournament, match, athlete, team);
843
+
844
+ if(!ba_title){ return }
845
+ return orders.push({ ...ba_order, title: ba_title })
846
+ }
847
+ let ep = external_prices.find(p => p.side == so.side);
848
+ let o_ep = external_prices.find(p => p.side != so.side);
849
+ if(ep && o_ep){
850
+ let ep_trade = MarketMaketHelpers.getTradeFromPrice(ep, side_id_response.reversed_side_id);
851
+ let ep_order = MarketMaketHelpers.getOrderFromTrade(ep_trade, 10);
852
+ let ep_title = MarketComponentHelpers.getOrderTitle(ep_order, market, event, tournament, match, athlete, team);
853
+ if(!ep_title){ return }
854
+ return orders.push({ ...ep_order, title: ep_title })
855
+ }
856
+ return
857
+ })
858
+
859
+ if(orders.length != 2){ return [] }
860
+
861
+ //OK!! Lets figured out the buffer odds!
862
+ let no_vig_trade_price = .5
863
+ let no_vig_o_price = .5
864
+ let no_vig_data = MarketMaketHelpers.getNoVigPrice(external_prices, market);
865
+ if(no_vig_data){
866
+ no_vig_o_price = no_vig_data.o_side_prob
867
+ no_vig_trade_price = no_vig_data.trade_side_prob
868
+ }
869
+
870
+ //Now lets add a buffer to each one based on the margin provided!
871
+ let margin = o_side_margin + trade_side_margin
872
+ let o_side_weight = o_side_margin / margin
873
+ let trade_side_weight = trade_side_margin / margin
874
+ no_vig_trade_price -= (margin * trade_side_weight)
875
+ let novig_trade_side_odds = Math.round(MarketMaketHelpers.calcAmericanOddsFromProbability(no_vig_trade_price))
876
+
877
+ no_vig_o_price -= (margin * o_side_weight)
878
+
879
+ let novig_o_side_odds = Math.round(MarketMaketHelpers.calcAmericanOddsFromProbability(no_vig_o_price))
880
+
881
+ //OK!!! Now lets add the propbabilities to the orders!
882
+ let trade_side_order = orders.find(o => o.side == market.trade_side);
883
+ let o_side_order = orders.find(o => o.side != market.trade_side);
884
+ if(!trade_side_order || !o_side_order){ return [] }
885
+
886
+ let higher_probability_order = no_vig_trade_price >= no_vig_o_price ? 'trade' : 'other'
887
+ let trade_side_stake = unit_size, o_side_stake = unit_size
888
+ if(higher_probability_order == 'trade'){
889
+ //If that is the stake, then the potential winnigns is
890
+ let pot_win = MarketMaketHelpers.calcPotentialWinnings(trade_side_stake, novig_trade_side_odds);
891
+ o_side_stake = MarketMaketHelpers.calcSaleValue(novig_o_side_odds, pot_win);
892
+ } else {
893
+ //If that is the stake, then the potential winnigns is
894
+ let pot_win = MarketMaketHelpers.calcPotentialWinnings(o_side_stake, novig_o_side_odds);
895
+ trade_side_stake = MarketMaketHelpers.calcSaleValue(novig_trade_side_odds, pot_win);
896
+ }
897
+
898
+ o_side_order = {
899
+ ...o_side_order,
900
+ probability: no_vig_o_price,
901
+ odds: novig_o_side_odds,
902
+ fulfill_action: 'drain',
903
+ expire_datetime: expire_datetime,
904
+ potential_winnings: MarketMaketHelpers.calcPotentialWinnings(o_side_stake, novig_o_side_odds),
905
+ open_amt: o_side_stake,
906
+ }
907
+ trade_side_order = {
908
+ ...trade_side_order,
909
+ probability: no_vig_trade_price,
910
+ odds: novig_trade_side_odds,
911
+ fulfill_action: 'drain',
912
+ expire_datetime: expire_datetime,
913
+ potential_winnings: MarketMaketHelpers.calcPotentialWinnings(trade_side_stake, novig_trade_side_odds),
914
+ open_amt: trade_side_stake,
915
+ }
916
+
917
+ return [ o_side_order, trade_side_order ]
918
+ }
756
919
  }
@@ -0,0 +1,444 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { Button, Text, TextInput, View } from "../../Components/Themed"
3
+ import type { BestAvailableOrderProps, EventProps, ExternalPriceProps, LocationProps, MarketProps, MatchProps, OrderProps, TournamentProps, TradeProps } from '../../types';
4
+ import { MarketComponentApi, MarketComponentHelpers } from '../api';
5
+ import { ActivityIndicator, FlatList, type ViewStyle } from 'react-native';
6
+ import { Icons } from '../../Components';
7
+ import { useColors } from '../../constants/useColors';
8
+ import { MarketMaketHelpers } from '../../MarketMaker/api';
9
+ import OrderGradeBar from './OrderGradeBar';
10
+ import WeightProgress from './WeightProgress';
11
+
12
+ type CreateMarketFormProps = {
13
+ float?:boolean,
14
+ style?:ViewStyle
15
+ contest_type:'team'|'tournament'|'match',
16
+ contest_id:string,
17
+ best_available_orders:BestAvailableOrderProps[],
18
+ my_orders:OrderProps[],
19
+ action_loading?:boolean,
20
+ market_id:string,
21
+ unit_size?:number,
22
+ location?:LocationProps,
23
+ coordinates?:{ latitude:number, longitude:number, [key:string]:any }
24
+ side_type?:'side'|'team'|'athlete',
25
+ side_id?:string,
26
+ onCancel:() => void,
27
+ onSubmitOrders:(orders:OrderProps[]) => void
28
+ }
29
+
30
+
31
+ const sections = ['o_side', 'submit', 'trade_side', 'draft_orders','my_orders', 'what_if'];
32
+ const CreateMarketForm = ({ float, action_loading, unit_size, location, coordinates, style, my_orders, best_available_orders, contest_type, contest_id, market_id, side_id, side_type, onCancel, onSubmitOrders }:CreateMarketFormProps) => {
33
+ const Colors = useColors();
34
+ const [ draft_orders, setDraftOrders ] = useState<OrderProps[]>([]);
35
+ const [ draft_data, setDraftData ] = useState<{
36
+ stake:string,
37
+ o_side_margin:number,
38
+ trade_side_margin:number
39
+ }>({
40
+ stake:unit_size?.toFixed(2) ?? '10',
41
+ o_side_margin: 0.02,
42
+ trade_side_margin: 0.02
43
+ });
44
+ const { o_side_margin, trade_side_margin, stake } = draft_data;
45
+ const [ form_data, setFormData ] = useState<{
46
+ loading:boolean,
47
+ markets:MarketProps[],
48
+ prices:ExternalPriceProps[],
49
+ trades:TradeProps[],
50
+ event?:EventProps,
51
+ tournament?:TournamentProps,
52
+ match?:MatchProps
53
+ }>({
54
+ loading:false,
55
+ markets: [],
56
+ prices: [],
57
+ trades: []
58
+ });
59
+
60
+ const { loading, markets, prices, event, tournament, match } = form_data;
61
+
62
+ const { contest_title } = MarketComponentHelpers.getContestDetails(contest_type, event, tournament, match);
63
+ const market = markets.find(mk => mk.market_id == market_id);
64
+
65
+ const orders = MarketComponentHelpers.setMarket(parseFloat(stake), contest_type, best_available_orders, prices, o_side_margin, trade_side_margin, market, event, tournament, match, undefined, undefined)
66
+ const no_vig_data = MarketMaketHelpers.getNoVigPrice(prices, market);
67
+
68
+
69
+ useEffect(() => {
70
+ MarketComponentApi.setEnvironment();
71
+ getFormData();
72
+ },[]);
73
+
74
+ const getFormData = async() => {
75
+ setFormData({ ...form_data, loading:true })
76
+ const mks = await MarketComponentApi.getMarkets();
77
+ let ev:EventProps | undefined, tourn:TournamentProps | undefined, mtch:MatchProps|undefined
78
+ if(contest_type == 'team'){
79
+ let evs = await MarketComponentApi.getEventsByEventIds([contest_id]);
80
+ ev = evs[0]
81
+ }
82
+ if(contest_type == 'tournament'){
83
+ let tourns = await MarketComponentApi.getTournamentsByTournamentIds([contest_id]);
84
+ tourn = tourns[0]
85
+ }
86
+ if(contest_type == 'match'){
87
+ let mtchs = await MarketComponentApi.getMatchesByMatchIds([contest_id]);
88
+ mtch = mtchs[0]
89
+ if(mtch){
90
+ let mtch_tourns = await MarketComponentApi.getTournamentsByTournamentIds([mtch.tournament_id]);
91
+ tourn = mtch_tourns[0]
92
+ }
93
+ }
94
+ let contest_prices = await MarketComponentApi.getExternalPrices(contest_type, contest_id, market_id);
95
+ //Get the correct prices
96
+ if(side_type){ contest_prices = contest_prices.filter(p => p.participant_type == side_type && p.participant_id == side_id) }
97
+ //First try to get consensus
98
+ contest_prices = contest_prices.filter(p => p.external_name == 'Consensus');
99
+ if(contest_prices.length == 0){
100
+ let available_books = [ ...new Set(contest_prices.map(p => p.external_name)) ]
101
+ contest_prices = contest_prices.filter(p => p.external_name == available_books[0]);
102
+ }
103
+
104
+ let contest_trades = await MarketComponentApi.getLatestTradesByEvents(contest_type, [contest_id]);
105
+
106
+
107
+ setFormData({
108
+ ...form_data,
109
+ loading:false,
110
+ markets: mks,
111
+ match: mtch,
112
+ event: ev,
113
+ tournament: tourn,
114
+ prices: contest_prices,
115
+ trades: contest_trades
116
+ });
117
+ }
118
+
119
+ const handleSubmitOrder = () => {
120
+ if(action_loading){ return }
121
+ if(draft_orders.length == 0){ return alert('Unable to submit!') }
122
+ if(!location){ return alert('Unable to create order without location') }
123
+ if(!location.legal_ind){ return alert('Unable to create order in this location') }
124
+ if(!coordinates?.latitude){ return alert('Need coordinates') }
125
+ let new_orders = draft_orders.map(o => {
126
+ o.region = location.label
127
+ o.location = coordinates
128
+ return o
129
+ });
130
+ onSubmitOrders(new_orders)
131
+ }
132
+
133
+ const handleUpdateMargin = (side:'other'|'trade', direction: 'increase'|'decrease') => {
134
+ let o_side = o_side_margin
135
+ let trade_side = trade_side_margin
136
+ if(side == 'other' && direction == 'increase'){ o_side += 0.001 }
137
+ if(side == 'other' && direction == 'decrease'){ o_side -= 0.001 }
138
+
139
+ if(side == 'trade' && direction == 'increase'){ trade_side += 0.001 }
140
+ if(side == 'trade' && direction == 'decrease'){ trade_side -= 0.001 }
141
+ let total_margin = o_side + trade_side
142
+ if(total_margin < 0.001){ return } //Cant go negative!!
143
+ setDraftData({ o_side_margin: o_side, trade_side_margin: trade_side, stake })
144
+
145
+ }
146
+
147
+ const renderOrders = (data:{ item:OrderProps, index:number }) => {
148
+ return (
149
+ <View style={{ flexGrow:1 }}>
150
+ <View style={{ padding:10 }}>
151
+ <Text theme='h1' textAlign='center'>{data.item.title}</Text>
152
+ </View>
153
+ </View>
154
+ )
155
+ }
156
+
157
+ const renderSections = (data:{item:string, index:number}) => {
158
+ switch(data.item){
159
+ case 'my_orders':
160
+ if(!market){ return <></> }
161
+ const hedges = MarketMaketHelpers.getHedgesFromPositions(my_orders, markets);
162
+ const hedge = hedges[0]
163
+ const o_side_stats = MarketMaketHelpers.getOrderStats(my_orders.filter(o => o.side != market.trade_side));
164
+ const t_side_stats = MarketMaketHelpers.getOrderStats(my_orders.filter(o => o.side == market.trade_side));
165
+ const stake_weight = MarketMaketHelpers.getWeight(o_side_stats.stake_potential_winnings, t_side_stats.stake_potential_winnings, market);
166
+ const at_risk = o_side_stats.stake_potential_winnings - t_side_stats.stake_potential_winnings
167
+ return (
168
+ <View type='footer' style={{ padding:10 }}>
169
+ <View transparent style={{ flexDirection:'row', alignItems:'center', padding:10 }}>
170
+ <View transparent style={{ flex:1 }}>
171
+ <Text theme='h1'>My Current Position</Text>
172
+ </View>
173
+ {hedge?
174
+ <View transparent>
175
+ {hedge.delayed_cash_draw ?
176
+ <Text theme='error' size={14}>-${hedge.delayed_cash_draw.toFixed(2)}</Text>
177
+ :
178
+ <Text theme='success' size={14}>${hedge.delayed_cash_no_draw.toFixed(2)}</Text>
179
+ }
180
+ <Text theme='description'>Hedged</Text>
181
+ </View>
182
+ :<></>}
183
+ </View>
184
+ <View transparent type='row'>
185
+ <View transparent style={{ flex:1, padding:5 }}>
186
+ <Text theme='h2' textAlign='center'>{o_side_stats.stake_potential_winnings.toFixed(2)}</Text>
187
+ </View>
188
+ <View transparent style={{ flex:1, padding:5 }}>
189
+ <Text theme='h2' textAlign='center'>{t_side_stats.stake_potential_winnings.toFixed(2)}</Text>
190
+ </View>
191
+ </View>
192
+ <WeightProgress
193
+ style={{ margin:10 }}
194
+ min_value={0}
195
+ max_value={100}
196
+ value={stake_weight.weighted_pct}
197
+ bar_height={18}
198
+ />
199
+ <View transparent type='row'>
200
+ {at_risk > 0 ?
201
+ <View transparent style={{ flex:1, padding:5 }}>
202
+ <Text theme='error' textAlign='center' style={{ marginTop:3 }}>${at_risk.toFixed(2)}</Text>
203
+ <Text theme='description' textAlign='center' style={{ marginTop:3 }}>At Risk</Text>
204
+ </View>
205
+ :<View style={{ flex:1 }} />}
206
+ {at_risk < 0 ?
207
+ <View transparent style={{ flex:1, padding:5 }}>
208
+ <Text theme='error' textAlign='center' style={{ marginTop:3 }}>${at_risk.toFixed(2)}</Text>
209
+ <Text theme='description' textAlign='center' style={{ marginTop:3 }}>At Risk</Text>
210
+ </View>
211
+ :<View style={{ flex:1 }} />}
212
+ </View>
213
+ </View>
214
+ )
215
+ case 'o_side':
216
+ if(draft_orders.length > 0){ return <></> }
217
+ if(!market){ return <></> }
218
+ let o_side_option = market.side_options.find(so => so.side != market.trade_side);
219
+ if(!o_side_option){ return <></> }
220
+ const o_side_order = orders.find(o => o.side != market.trade_side);
221
+ if(!o_side_order){ return <></> }
222
+ const o_side_price = prices.find(p => p.side != market.trade_side);
223
+ const o_side_no_vig = no_vig_data?.o_side_odds
224
+ const o_best_available = best_available_orders.find(o => o.market_id == market_id && o.side != market.trade_side)
225
+ //const my_o_side_open = my_orders.filter(o => o.market_id == market_id && o.side != market.trade_side);
226
+ //const my_open_stats = MarketMaketHelpers.getOrderStats(my_o_side_open, o_best_available);
227
+ return (
228
+ <View style={{ borderWidth:1, borderColor:Colors.borders.light, margin:10 }}>
229
+ <View type='row' style={{ padding:10, borderBottomWidth:1, borderColor:Colors.borders.light }}>
230
+ <View transparent style={{ flex:1 }}>
231
+ <Text theme='h2'>{o_side_order.title}</Text>
232
+ <Text theme='description' style={{ marginTop:3 }}>${o_side_order.open_amt.toFixed(2)} to win ${o_side_order.potential_winnings.toFixed(2)}</Text>
233
+ </View>
234
+ <Text theme='h1'>${o_side_order.open_amt.toFixed(2)}</Text>
235
+ <View type='row' style={{ marginLeft:10 }}>
236
+ <Button float onPress={() => handleUpdateMargin('other', 'increase')}>
237
+ <Icons.ChevronIcon direction='left' size={8} color={Colors.text.h1} />
238
+ </Button>
239
+ <View style={{ paddingLeft:10, paddingRight:10 }}>
240
+ <Text theme='h1' textAlign='center'>{(o_side_order.probability * 100).toFixed(2)}%</Text>
241
+ <Text theme='light' style={{ marginTop:3 }} textAlign='center'>{MarketComponentHelpers.getOddsLabel(o_side_order.odds)}</Text>
242
+ </View>
243
+ <Button float onPress={() => handleUpdateMargin('other', 'decrease')}>
244
+ <Icons.ChevronIcon direction='right' size={8} color={Colors.text.h1} />
245
+ </Button>
246
+ </View>
247
+ </View>
248
+ {o_best_available ?
249
+ <View type='row' style={{ padding:10 }}>
250
+ <View transparent style={{flex:1}}>
251
+ <Text theme='h1'>{o_best_available.title}</Text>
252
+ {o_best_available.grade ?
253
+ <OrderGradeBar style={{ alignSelf:'flex-start', marginTop:3 }} grade={o_best_available.grade} view_type='card' onSelectGrade={() => console.log('')}/>
254
+ :<></>}
255
+ </View>
256
+ <View style={{ alignItems:'flex-end' }}>
257
+ <Text theme='h2'>{MarketComponentHelpers.getOddsLabel(o_best_available.odds)}</Text>
258
+ <Text theme='success'>${o_best_available.open_amt.toFixed(2)} Available</Text>
259
+ </View>
260
+ <Button
261
+ title='BUY'
262
+ type='success'
263
+ loading={action_loading}
264
+ style={{ padding:10, marginLeft:10, opacity: action_loading ? 0.5:1 }}
265
+ disabled={action_loading}
266
+ onPress={() => {
267
+ let side_ids = MarketComponentHelpers.getSideIds(contest_type, o_side_option, market, event, tournament, match, undefined, undefined);
268
+ if(!side_ids){ return }
269
+ let trade = MarketMaketHelpers.getTradeFromAvailableOrder(o_best_available, side_ids.reversed_side_id);
270
+ let order = MarketMaketHelpers.getOrderFromTrade(trade, unit_size ?? 10, o_best_available.order_id);
271
+ order.title = o_best_available.title
272
+ setDraftOrders([order])
273
+ }}
274
+ />
275
+ </View>
276
+ :<></>}
277
+ {o_side_price && o_side_no_vig ?
278
+ <View type='footer' style={{ flexDirection:'row', alignItems:'center', padding:10 }}>
279
+ <View transparent style={{ flex:1 }}>
280
+ <Text theme='h1'>{o_side_price.external_name}</Text>
281
+ <Text theme='light' style={{ marginTop:3 }}>External price with vig removed</Text>
282
+ </View>
283
+ <Text theme='h2'>{MarketComponentHelpers.getOddsLabel(o_side_no_vig)}</Text>
284
+ </View>
285
+ :<></>}
286
+ </View>
287
+
288
+ )
289
+ case 'submit':
290
+ if(draft_orders.length > 0){ return <></> }
291
+ return (
292
+ <View type='header' style={{ flexDirection:'row', padding:10 }}>
293
+ <TextInput
294
+ value={stake}
295
+ style={{ width:100, textAlign:'center' }}
296
+ onChangeText={(text) => setDraftData({ ...draft_data, stake:text })}
297
+ />
298
+ <Button
299
+ style={{ flex:2, marginLeft:10, opacity: action_loading?0.5:1 }}
300
+ type='success'
301
+ loading={action_loading}
302
+ disabled={action_loading}
303
+ title='SET MARKET'
304
+ onPress={() => setDraftOrders(orders)}
305
+ />
306
+ </View>
307
+ )
308
+ case 'trade_side':
309
+ if(draft_orders.length > 0){ return <></> }
310
+ if(!market){ return <></> }
311
+ let trade_side_option = market.side_options.find(so => so.side == market.trade_side);
312
+ if(!trade_side_option){ return <></> }
313
+ const trade_side_order = orders.find(o => o.side == market.trade_side);
314
+ if(!trade_side_order){ return <></> }
315
+ const trade_side_price = prices.find(p => p.side == market.trade_side);
316
+ const trade_side_no_vig_odds = no_vig_data?.trade_side_odds
317
+ const t_best_available = best_available_orders.find(o => o.market_id == market_id && o.side == market.trade_side)
318
+ return (
319
+ <View style={{ borderWidth:1, borderColor:Colors.borders.light, margin:10 }}>
320
+ <View type='row' style={{ padding:10 }}>
321
+ <View transparent style={{ flex:1 }}>
322
+ <Text theme='h2'>{trade_side_order.title}</Text>
323
+ <Text theme='description' style={{ marginTop:3 }}>${trade_side_order.open_amt.toFixed(2)} to win ${trade_side_order.potential_winnings.toFixed(2)}</Text>
324
+ </View>
325
+ <Text theme='h1'>${trade_side_order.open_amt.toFixed(2)}</Text>
326
+ <View type='row' style={{ marginLeft:10 }}>
327
+ <Button float onPress={() => handleUpdateMargin('trade', 'increase')}>
328
+ <Icons.ChevronIcon direction='left' size={8} color={Colors.text.h1} />
329
+ </Button>
330
+ <View style={{ paddingLeft:10, paddingRight:10 }}>
331
+ <Text theme='h1'>{(trade_side_order.probability * 100).toFixed(2)}%</Text>
332
+ <Text theme='light' style={{ marginTop:3 }} textAlign='center'>{MarketComponentHelpers.getOddsLabel(trade_side_order.odds)}</Text>
333
+ </View>
334
+ <Button float onPress={() => handleUpdateMargin('trade', 'decrease')}>
335
+ <Icons.ChevronIcon direction='right' size={8} color={Colors.text.h1} />
336
+ </Button>
337
+ </View>
338
+ </View>
339
+ {t_best_available ?
340
+ <View type='row' style={{ padding:10 }}>
341
+ <View transparent style={{flex:1}}>
342
+ <Text theme='h1'>{t_best_available.title}</Text>
343
+ {t_best_available.grade ?
344
+ <OrderGradeBar style={{ alignSelf:'flex-start', marginTop:3 }} grade={t_best_available.grade} view_type='card' onSelectGrade={() => console.log('')}/>
345
+ :<></>}
346
+ </View>
347
+ <View style={{ alignItems:'flex-end' }}>
348
+ <Text theme='h2'>{MarketComponentHelpers.getOddsLabel(t_best_available.odds)}</Text>
349
+ <Text theme='success'>${t_best_available.open_amt.toFixed(2)} Available</Text>
350
+ </View>
351
+ <Button
352
+ title='BUY'
353
+ type='success'
354
+ style={{ padding:10, marginLeft:10, opacity: action_loading ? 0.5:1 }}
355
+ disabled={action_loading}
356
+ onPress={() => {
357
+ let side_ids = MarketComponentHelpers.getSideIds(contest_type, trade_side_option, market, event, tournament, match, undefined, undefined);
358
+ if(!side_ids){ return }
359
+ let trade = MarketMaketHelpers.getTradeFromAvailableOrder(t_best_available, side_ids.reversed_side_id);
360
+ let order = MarketMaketHelpers.getOrderFromTrade(trade, unit_size ?? 10, t_best_available.order_id);
361
+ order.title = t_best_available.title
362
+ setDraftOrders([order])
363
+ }}
364
+ />
365
+ </View>
366
+ :<></>}
367
+ {trade_side_price && trade_side_no_vig_odds ?
368
+ <View type='footer' style={{ flexDirection:'row', alignItems:'center', padding:10 }}>
369
+ <View transparent style={{ flex:1 }}>
370
+ <Text theme='h1'>{trade_side_price.external_name}</Text>
371
+ <Text theme='light' style={{ marginTop:3 }}>External price with vig removed</Text>
372
+ </View>
373
+ <Text theme='h2'>{MarketComponentHelpers.getOddsLabel(trade_side_no_vig_odds)}</Text>
374
+ </View>
375
+ :<></>}
376
+ </View>
377
+ )
378
+ case 'draft_orders':
379
+ if(draft_orders.length == 0){ return <></> }
380
+ return (
381
+ <View style={{ flexDirection:'row', flexWrap:'wrap' }}>
382
+ {draft_orders.map((o,i) => {
383
+ return renderOrders({ item: o, index:i })
384
+ })}
385
+ </View>
386
+ )
387
+ case 'what_if':return <></>
388
+ default: return <></>
389
+ }
390
+ }
391
+
392
+ const total_margin = o_side_margin + trade_side_margin
393
+ return (
394
+ <View float={float} style={{ ...style }}>
395
+ <View type='header' style={{ flexDirection:'row', alignItems:'center', padding:10, borderTopLeftRadius:8, borderTopRightRadius:8 }}>
396
+ <View transparent style={{ flex:1 }}>
397
+ <Text theme='h1'>{contest_title}</Text>
398
+ </View>
399
+ <View transparent style={{ justifyContent:'center', alignItems:'center' }}>
400
+ <Text theme='h2' color={total_margin > 0.06 ? Colors.text.error : total_margin > 0.045 ? Colors.text.warning : Colors.text.success}>{(total_margin*100).toFixed(2)}%</Text>
401
+ <Text theme='description' textAlign='center'>Margin</Text>
402
+ </View>
403
+ </View>
404
+ <View type='body' style={{ flex:1 }}>
405
+ {loading ?
406
+ <ActivityIndicator size='large' color={Colors.text.h1} />
407
+ :<></>}
408
+ <FlatList
409
+ key={'create_market_sections'}
410
+ keyExtractor={item => item}
411
+ renderItem={renderSections}
412
+ data={sections}
413
+ />
414
+ </View>
415
+ {draft_orders.length == 0 ?
416
+ <View type='footer' style={{ flexDirection:'row', alignItems:'center', padding:10, borderBottomRightRadius:8, borderBottomLeftRadius:8 }}>
417
+ <Button
418
+ style={{ flex:1 }}
419
+ type='action'
420
+ title='CLOSE'
421
+ onPress={() => onCancel()}
422
+ />
423
+ </View>
424
+ :
425
+ <View type='footer' style={{ flexDirection:'row', alignItems:'center', padding:10, borderBottomRightRadius:8, borderBottomLeftRadius:8 }}>
426
+ <Button
427
+ style={{ flex:1 }}
428
+ type='error'
429
+ title='CANCEL'
430
+ onPress={() => setDraftOrders([])}
431
+ />
432
+ <Button
433
+ style={{ flex:2, marginLeft:5 }}
434
+ type='success'
435
+ title='SUBMIT ORDERS'
436
+ onPress={() => handleSubmitOrder()}
437
+ />
438
+ </View>
439
+ }
440
+ </View>
441
+ )
442
+ }
443
+
444
+ export default CreateMarketForm