', '').replace('£', '').replace('$', '')
137 | return [stattrak, wear, price]
138 |
139 |
140 | def csgostash_price(ids, skin):
141 | remove = ['(', ')', "'", '.', '<', '>']
142 | prices = []
143 | converted_skin = skin.replace(' | ', '-').replace(' ', '-').replace('\\u9f8d\\u738b', '%E9%BE%8D%E7%8E%8B').replace(
144 | '_', '-')
145 | for rem in remove:
146 | converted_skin = converted_skin.replace(rem, '')
147 | id_file = open(ids, 'r', encoding='utf-8')
148 | try:
149 | id_contents = (id_file.read().split(converted_skin))[1]
150 | s_id = id_contents.replace('<', '').replace('>', '')
151 | website = requests.get((f'https://csgostash.com/skin/{s_id}'))
152 | r = website.text.split('')
153 | if 'StatTrak' in r[2].split('\n'):
154 | for i in range(2, 2 + 10):
155 | values = r[i].split('')[0]
156 | prices.append(extract(values))
157 | else:
158 | for i in range(2, 2 + 5):
159 | values = r[i].split('')[0]
160 | prices.append(extract(values))
161 | nst_prices = []
162 | st_prices = []
163 | nst_total = 0
164 | st_total = 0
165 | for i in range(0, len(prices)):
166 | if not prices[i][0]:
167 | if prices[i][2].replace(' ', '') != 'NotPossible':
168 | if prices[i][2].replace(' ', '') != 'NoRecentPrice':
169 | nst_prices.append(float(prices[i][2].replace(',', '')))
170 | else:
171 | if prices[i][2].replace(' ', '') != 'NotPossible':
172 | if prices[i][2].replace(' ', '') != 'NoRecentPrice':
173 | st_prices.append(float(prices[i][2].replace(',', '')))
174 | for nst_price in nst_prices:
175 | nst_total = nst_total + nst_price
176 | for st_price in st_prices:
177 | st_total = st_total + st_price
178 | if st_total != 0:
179 | avg_stattrak = str(st_total / (len(st_prices)))
180 | else:
181 | avg_stattrak = 'NO PRICE'
182 | if nst_total != 0:
183 | avg_nonstattrak = str(nst_total / (len(nst_prices)))
184 | else:
185 | avg_nonstattrak = 'NO PRICE'
186 | avg_prices = [avg_nonstattrak, avg_stattrak]
187 | except KeyError as e:
188 | print(converted_skin, e)
189 | id_file.close()
190 | return avg_prices
191 |
192 |
193 | def skin_prices(ids, inp, out):
194 | total_time = time.time()
195 | print('Getting all case skin prices (Approx 7 mins):')
196 | skins = []
197 | ifile = open(str(inp), 'r')
198 | ofile = open(str(out), 'w+')
199 | ilines = ifile.readlines()
200 | for iline in ilines:
201 | start_time = time.time()
202 | amount = '{'
203 | cases = iline.split(':::')
204 | case = cases[0]
205 | for all_wear in all_wears:
206 | count = iline.count(all_wear)
207 | amount = f"{amount} '{all_wear}':{count},"
208 | amount = ast.literal_eval((amount + '}').replace(',}', '}'))
209 | for skin_list in ast.literal_eval(cases[2]):
210 | wear = skin_list[1]
211 | skin = skin_list[0]
212 | probability = probabilites[wear] / amount[wear] / 100
213 | price = csgostash_price(ids, skin)
214 | skins.append([case, skin, price, probability])
215 | print(f'Searched - {case}, took {time.time() - start_time} Seconds')
216 | for skin in skins:
217 | ofile.write(str(skin) + '\n')
218 | ofile.close()
219 | print(f'Compleated searching skin prices, took - {(time.time() - total_time) / 60} mins')
220 |
221 |
222 | def archive(files):
223 | if os.path.exists(f'current/'):
224 | shutil.rmtree('current')
225 | os.makedirs('current')
226 | else:
227 | os.makedirs('current')
228 | if not os.path.exists('archive'):
229 | os.makedirs('archive')
230 |
231 | for file in files:
232 | shutil.copy(f'{file}', f'archive/{add_date(file)}')
233 | os.rename(str(file), f'current/{file}')
234 |
235 |
236 | def item_case_search(files):
237 | import multiprocessing
238 | case_file = files[0]
239 | price_file = files[1]
240 | stash_ids = files[2]
241 | processes = []
242 | p = multiprocessing.Process(target=cases, args=[case_file])
243 | p.start()
244 | processes.append(p)
245 | p = multiprocessing.Process(target=csgo_stash_ids, args=[stash_ids])
246 | p.start()
247 | processes.append(p)
248 | for p in processes:
249 | p.join()
250 | skin_prices(stash_ids, case_file, price_file)
251 | # if not os.path.exists(stash_ids):
252 | # csgo_stash_ids(stash_ids)
253 |
--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------
1 | import time
2 | import os
3 | import ast
4 | from Prices import price_grabber as pg
5 |
6 |
7 | def avg_revenue_per_case():
8 | probabilities = []
9 | skins = []
10 | cases = []
11 | if not os.path.exists('temp'):
12 | os.makedirs('temp')
13 | out_file = open('temp/values.txt', 'w+')
14 | inp_file = open('skins.txt', 'r')
15 | for i in inp_file.readlines():
16 | skins.append(i.replace('\n', ''))
17 | for skin in skins:
18 | cases.append(ast.literal_eval(skin)[0])
19 | cases = list(dict.fromkeys(cases))
20 | for case in cases:
21 | for i in range(0, len(skins)):
22 | if ast.literal_eval(skins[i])[0] == case:
23 | stat_trak_prob = float(ast.literal_eval(skins[i])[2][1].replace('NO PRICE', str(1500))) * ((1 / 10) * float(ast.literal_eval(skins[i])[3]))
24 | prob = float(ast.literal_eval(skins[i])[2][0].replace('NO PRICE', str(500))) * ((9 / 10) * float(ast.literal_eval(skins[i])[3]))
25 | probabilities.append([case, stat_trak_prob + prob])
26 | new_list = []
27 | case_prices = open('cases.txt', 'r')
28 | dic = '{'
29 | for case_price_line in case_prices.readlines():
30 | case_price_line = case_price_line.split(':::')
31 | dic = dic + f'"{case_price_line[0]}":"{case_price_line[1]}",'
32 | case_price_dic = ast.literal_eval((dic + '}').replace(',}', '}'))
33 | for case in cases:
34 | addition = 0
35 | for pro in probabilities:
36 | if pro[0] == case:
37 | addition = addition + pro[1]
38 | new_list.append([case, addition - 2.15 - float(case_price_dic[case])])
39 | inp_file.close()
40 | out_file.close()
41 | return new_list
42 |
43 |
44 | def sort(unsorted_list):
45 | sorted_list = sorted(unsorted_list, key=lambda x: x[1])
46 | return sorted_list
47 |
48 |
49 | def result_file_write(file_name, sorted_list):
50 | file = open(file_name, 'w+')
51 | for item in sorted_list:
52 | line = f'{item[0]} ~ {item[1]}\n'
53 | file.write(line)
54 | file.close()
55 |
56 |
57 | if __name__ == '__main__':
58 | start_time = time.time()
59 | case_file = 'cases.txt'
60 | price_file = 'skins.txt'
61 | stash_ids = 'csgo_stash_ids.txt'
62 | result_file = 'results.txt'
63 | files = [case_file, price_file, stash_ids, result_file]
64 | pg.item_case_search(files)
65 | sorted_list = (sort(avg_revenue_per_case()))[::-1]
66 | print(sorted_list)
67 | result_file_write(result_file, sorted_list)
68 | print(f'Steam Case Calc took - {(time.time() - start_time) / 60} Mins')
69 | pg.archive(files)
70 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | ## CSGO Case Data Analysis (Currently without knives/gloves)
2 |
3 | Works out average profit per case (Currently only uses gun skin prices), the code only currently accurately works for GBP but can easily be changed in the main.py file (So without changes the code will crash or be inaccurate unless you live in UK).
4 | The code takes a while to run as Steam has a limit on requests, so it compiles data from CSGOStash as well as SteamMarket, but only uses steam market prices.
5 | The code should have no need to be changed when a new case gets released, unless they do something odd.
6 |
7 | ## How It Calculates Values
8 |
9 | Gets average price of each skin of each rarity and stat-track of each case according to the rarity of each, then calculates cost of opening each case. Gets average cost and minus's average outcome of each case.
10 |
11 | ## Instructions
12 |
13 | - Install python 3
14 | - Install requests module - `pip install requests`
15 | - It can take about 27 mins to compile all the data it needs
16 | - Run main.py
17 | - Program outputs the result in the results.txt file located in /current
18 |
19 | ## Help
20 |
21 | If you have issues,
22 | Message on the github page
23 |
24 | But the code should work fine
25 |
26 |
27 | ## Example Results (10/05/2022):
28 | ```
29 | CS:GO Weapon Case 3 ~ -0.49065092733333415
30 | Shadow Case ~ -0.5353895642857143
31 | Operation Wildfire Case ~ -0.7451264979999995
32 | Falchion Case ~ -0.8690617335555553
33 | Horizon Case ~ -0.9773799866666665
34 | Revolver Case ~ -1.0868887199999997
35 | Prisma Case ~ -1.1622260504126984
36 | Operation Vanguard Weapon Case ~ -1.1663884526666666
37 | Prisma 2 Case ~ -1.2546098422857141
38 | CS20 Case ~ -1.3001250133333335
39 | Danger Zone Case ~ -1.3088801385714286
40 | Snakebite Case ~ -1.333511416
41 | Fracture Case ~ -1.3559560880000001
42 | Shattered Web Case ~ -1.3802351561904762
43 | Operation Phoenix Weapon Case ~ -1.5493879913888886
44 | Operation Broken Fang Case ~ -1.6023493226666667
45 | Chroma 2 Case ~ -1.6476826024999998
46 | Dreams & Nightmares Case ~ -1.7349554659047621
47 | Spectrum Case ~ -1.761462312857143
48 | Chroma 3 Case ~ -1.8120143757142855
49 | Clutch Case ~ -1.8141858224761904
50 | Chroma Case ~ -1.834853867333333
51 | Spectrum 2 Case ~ -1.8980511855238096
52 | Gamma Case ~ -1.9623437694285712
53 | eSports 2014 Summer Case ~ -1.966613270666666
54 | Operation Riptide Case ~ -2.1354644559047617
55 | Gamma 2 Case ~ -2.1760050912380953
56 | Winter Offensive Weapon Case ~ -2.2364220816666665
57 | eSports 2013 Winter Case ~ -2.262996812222222
58 | CS:GO Weapon Case 2 ~ -2.3633042296666655
59 | Huntsman Weapon Case ~ -2.810259526666666
60 | Glove Case ~ -3.650142872
61 | Operation Breakout Weapon Case ~ -3.915997794722222
62 | Operation Hydra Case ~ -8.945994573523809
63 | Operation Bravo Case ~ -19.98586110333333
64 | eSports 2013 Case ~ -20.09925230222222
65 | CS:GO Weapon Case ~ -20.73005133333333
66 | ```
67 |
--------------------------------------------------------------------------------