Are you a Quiet Speculation member?
If not, now is a perfect time to join up! Our powerful tools, breaking-news analysis, and exclusive Discord channel will make sure you stay up to date and ahead of the curve.
Welcome back! Last week I discussed the technologies I'm basing my data warehouse on, and did some reporting on cards I thought were worth shorting based on the Pro Tour results. This week, I'd like to go into how to construct an object oriented data model and then focus a bit on the new face of standard, and what that looks like for MTGO speculating.
Automation:
When storing data, the data model you employ can decide a lot about how you will report on that data, and have some easy to miss consequences deeper into a project. I want to share a bit about the model I'm using, and some issues I've encountered along the way!
In the previous article, I talked about how I chose to use a relational database. This is a pretty common decision in a modern database, but if you aren't familiar with this, it might take some explaining.
Here's an example of a flat file, something you might open in Excel:
Card Name | Set | Card Type | Card Rarity |
Mutavault | Magic 2014 | Land | Rare |
Mutavault | Morningtide | Land | Rare |
Mutavault | Promotional | Land | Rare |
Yawgmoth's Will | Urza's Saga | Sorcery | Rare |
Yawgmoth's Will | Promotional | Sorcery | Rare |
A relational database takes the flat file and expands it, by separating out common elements and linking them with keys. A simple way to expand the above table into a two table setup would be as follows:
Card Type | Key |
Land | 111 |
Sorcery | 222 |
Creature | 333 |
Card Name | Set | Card Type | Card Rarity |
Mutavault | Magic 2014 | 111 | Rare |
Mutavault | Morningtide | 111 | Rare |
Mutavault | Promotional | 111 | Rare |
Yawgmoth's Will | Urza's Saga | 222 | Rare |
Yawgmoth's Will | Promotional | 222 | Rare |
By using a key in the card table, I can now reference the type of card by a key and create a relationship between a card record and a type record. Looking at the card table, there may be tables that could be spun off.
This may look like a lot of work, but it provides several key advantages. The primary advantage in this case is that card type is now written to the database only once for each value and then related to each card of that type. If Wizards decided to errata the type from "Instant" to "Fast Spell", I would change one record, and that change would reflect on the thousands of cards sharing that type quickly. It also provides performance benefits. If I wanted to know how many card types there were in a flat file, I'd have to search a table of thousands of cards for all the unique card types. In the relational model, I can answer that question very quickly by presenting all the records in the card type table.
In my scenario, I want to build a model that can store the MTGO event data that wizards provides. To do that, I have to come up with a logical way to break down the data into separate tables with keys to link them. Since the data is event data, an event table is a logical first step. In each event there are players, and decks, so those could form the next two tables. Finally, each deck is composed of cards, so there had better be a card table.
This is where my data model stopped originally, which turned out to be a very critical mistake. I assumed at the time that since I was only reporting on event data, my data model would be card version agnostic. When you play a Mutavault, it doesn't really matter if you are playing the new M14 Mutavault or a PRM version of Mutavault. This decision was very shortsighted. My primary goal for the whole project was to tie these event numbers back to financial numbers. To do so, I would also need card versions PRM Mutavault has a completely different price than the M14 Mutavault and eventually these prices differences would become very important (when I started my bot chain). So I went back and added sets and table that would link sets to cards that I called "card In set." I also dropped the user table because I realized I didn't have too much interest in tracking specific users results.
This is what my basic data model looks like currently:
This entity-relationship diagram (ERD for short) is a way of visualizing tables in a database. The lines represent relationships, whereby one table stores the key of another table and cements the link. Card became the primary object because all my reports center around cards. This has an advantage for reporting, as I can get most of the important information I need right off the card table.
If you have any questions about this type of data model, or how I structured mine please feel free to ask in the comments. Next week I plan to go into a bit of detail on how I physically get the data from wizards and push it into these tables. There might be some code (I've been told by a few people that they are interested in this sort of thing so hopefully I'm not boring too many people)!
Speculation:
Now to the reporting. I've actually held off looking at this standard report until I started writing this article, so I'm really excited to see how standard is shaping up since the Pro Tour. The table I present to you is all the standard mythics and rares reported in decks by Wizards over the last 2 weeks for Standard. I'll include my analysis at the bottom after the report!
Standard Mythics:
Card Name | Bot Buy Price | Standard Quantity Last 7 Days | Standard Quantity Previous 7 Days | Standard Decks Last 7 Days | Standard Decks Previous 7 Days |
Jace, Architect of Thought | 22.25 | 414 | 216 | 177 | 72 |
Master of Waves | 7.2 | 348 | 78 | 87 | 20 |
Thassa, God of the Sea | 7.35 | 331 | 74 | 86 | 21 |
Blood Baron of Vizkopa | 14.8 | 172 | 125 | 97 | 59 |
Erebos, God of the Dead | 5.95 | 171 | 54 | 151 | 45 |
Domri Rade | 17 | 165 | 126 | 52 | 43 |
Elspeth, Sun's Champion | 13.2 | 162 | 129 | 112 | 80 |
Polukranos, World Eater | 8.4 | 162 | 111 | 46 | 48 |
Garruk, Caller of Beasts | 15.7 | 146 | 83 | 41 | 34 |
Sphinx's Revelation | 32.75 | 139 | 146 | 45 | 47 |
Obzedat, Ghost Council | 14.8 | 134 | 119 | 55 | 61 |
Stormbreath Dragon | 10.9 | 122 | 126 | 40 | 39 |
Xenagos, the Reveler | 6.75 | 101 | 35 | 58 | 19 |
Chandra, Pyromaster | 15.3 | 88 | 170 | 50 | 93 |
Nylea, God of the Hunt | 3 | 86 | 88 | 38 | 33 |
Rakdos's Return | 7.25 | 50 | 89 | 30 | 55 |
Voice of Resurgence | 27.25 | 46 | 246 | 12 | 62 |
Ashiok, Nightmare Weaver | 7.6 | 46 | 26 | 18 | 10 |
Purphoros, God of the Forge | 3.95 | 44 | 27 | 19 | 18 |
Jace, Memory Adept | 4.05 | 40 | 81 | 26 | 45 |
Ajani, Caller of the Pride | 4.1 | 34 | 52 | 18 | 41 |
Liliana of the Dark Realms | 3.35 | 28 | 15 | 16 | 8 |
Archangel of Thune | 10 | 18 | 50 | 9 | 20 |
Vraska the Unseen | 4.1 | 13 | 7 | 7 | 6 |
Trostani, Selesnya's Voice | 3.75 | 13 | 88 | 8 | 74 |
Heliod, God of the Sun | 2.15 | 13 | 12 | 7 | 8 |
Kalonian Hydra | 7.65 | 7 | 56 | 3 | 24 |
Shadowborn Demon | 3.4 | 6 | 19 | 5 | 11 |
Deadbridge Chant | 0.7 | 4 | 2 | 4 | 1 |
Legion's Initiative | 2.45 | 2 | 0 | 1 | 0 |
Aurelia, the Warleader | 1.65 | 2 | 18 | 2 | 16 |
Gideon, Champion of Justice | 3.25 | 2 | 5 | 1 | 5 |
Prime Speaker Zegana | 2.8 | 2 | 3 | 1 | 1 |
Aurelia's Fury | 2.5 | 2 | 3 | 2 | 1 |
Hythonia the Cruel | 0.37 | 2 | 2 | 2 | 1 |
Deathpact Angel | 0.28 | 1 | 0 | 1 | 0 |
Scourge of Valkas | 0.48 | 1 | 4 | 1 | 1 |
Jarad, Golgari Lich Lord | 1.25 | 1 | 0 | 1 | 0 |
Master Biomancer | 3.5 | 1 | 0 | 1 | 0 |
Ashen Rider | 0.48 | 1 | 2 | 1 | 1 |
Master of Cruelties | 0.58 | 0 | 1 | 0 | 1 |
Maze's End | 2.35 | 0 | 8 | 0 | 2 |
Ral Zarek | 4.55 | 0 | 2 | 0 | 1 |
Primeval Bounty | 3.5 | 0 | 4 | 0 | 3 |
Duskmantle Seer | 2.15 | 0 | 2 | 0 | 1 |
Angel of Serenity | 5 | 0 | 8 | 0 | 5 |
Standard Rares:
Card Name | Bot Buy Price | Standard Quantity Last 7 Days | Standard Quantity Previous 7 Days | Standard Decks Last 7 Days | Standard Decks Previous 7 Days |
Mutavault | 11.4 | 832 | 515 | 302 | 207 |
Thoughtseize | 8.25 | 709 | 287 | 217 | 107 |
Hero's Downfall | 8.1 | 675 | 238 | 202 | 102 |
Nightveil Specter | 1.25 | 604 | 125 | 161 | 33 |
Desecration Demon | 3.7 | 602 | 270 | 157 | 72 |
Lifebane Zombie | 6.05 | 508 | 192 | 163 | 59 |
Underworld Connections | 0.62 | 439 | 187 | 181 | 90 |
Mizzium Mortars | 2.35 | 432 | 544 | 162 | 198 |
Temple of Silence | 2.25 | 422 | 211 | 125 | 61 |
Boros Reckoner | 6.7 | 416 | 629 | 108 | 162 |
Nykthos, Shrine to Nyx | 4.25 | 401 | 119 | 198 | 61 |
Tidebinder Mage | 0.44 | 343 | 80 | 89 | 20 |
Godless Shrine | 3.55 | 321 | 253 | 81 | 64 |
Ash Zealot | 1.65 | 319 | 403 | 81 | 101 |
Chandra's Phoenix | 1.45 | 308 | 449 | 80 | 113 |
Ratchet Bomb | 0.34 | 299 | 175 | 161 | 96 |
Whip of Erebos | 1.2 | 265 | 118 | 164 | 82 |
Temple of Deceit | 2.2 | 251 | 69 | 76 | 20 |
Pack Rat | 0.036 | 238 | 21 | 113 | 10 |
Pithing Needle | 1.5 | 222 | 223 | 166 | 129 |
Burning Earth | 1.25 | 212 | 335 | 79 | 109 |
Sacred Foundry | 3.65 | 208 | 236 | 52 | 59 |
Soldier of the Pantheon | 1.45 | 202 | 86 | 54 | 24 |
Stomping Ground | 3.2 | 200 | 148 | 50 | 37 |
Temple of Abandon | 1 | 199 | 128 | 50 | 33 |
Cyclonic Rift | 0.36 | 190 | 55 | 92 | 29 |
Sylvan Caryatid | 2.1 | 188 | 138 | 48 | 38 |
Hallowed Fountain | 3.1 | 186 | 184 | 47 | 46 |
Supreme Verdict | 1.35 | 179 | 177 | 47 | 48 |
Bident of Thassa | 0.17 | 176 | 35 | 84 | 18 |
Precinct Captain | 0.68 | 167 | 60 | 44 | 19 |
Temple of Triumph | 1.8 | 165 | 132 | 49 | 46 |
Detention Sphere | 0.6 | 160 | 171 | 58 | 57 |
Mistcutter Hydra | 0.88 | 156 | 145 | 58 | 55 |
Watery Grave | 3.25 | 150 | 64 | 38 | 16 |
Firedrinker Satyr | 0.3 | 149 | 274 | 42 | 73 |
Scavenging Ooze | 5.8 | 141 | 209 | 56 | 87 |
Anger of the Gods | 1.05 | 140 | 194 | 49 | 81 |
Fiendslayer Paladin | 2.4 | 129 | 80 | 51 | 26 |
Xathrid Necromancer | 1.35 | 123 | 41 | 35 | 11 |
Chained to the Rocks | 0.66 | 123 | 105 | 46 | 38 |
Hammer of Purphoros | 0.25 | 112 | 133 | 80 | 96 |
Arbor Colossus | 0.29 | 99 | 24 | 36 | 11 |
Blood Crypt | 2.35 | 96 | 152 | 24 | 38 |
Dreadbore | 0.35 | 70 | 112 | 25 | 44 |
Temple Garden | 2.55 | 56 | 278 | 14 | 72 |
Overgrown Tomb | 2.75 | 52 | 84 | 13 | 21 |
Assemble the Legion | 0.38 | 45 | 42 | 23 | 26 |
Boon Satyr | 0.94 | 44 | 242 | 16 | 65 |
Here are the complete tables in google doc form (including Rares 51+).
My thoughts:
- Mono Blue is definitely king on MTGO right now with the top 3 played mythics. Master of Waves and Thassa, God of the Sea have seen huge gains in play amount and come down significantly from their PT spike. Today (October 23rd) is the same day last year that RTR mythics were at their lowest point, after which prices began to jump. I will be watching Master of Waves and Thassa, God of the Sea over the next few days looking for the lowest possible entry point, looking for a quick 2 week flip once redemption begins.
- We discussed this last week, but Chandra, Pyromaster has dropped in popularity online, causing the price to correct downward so it appears that selling was a correct call. This has also head true for Chandra's Phoenix!
- Voice of Resurgence has seen a huge drop in popularity for Standard. This has been mentioned in the forums as well, but there should be an opportunity to grab these before Modern season where they should see a nice boost. The biggest variable will be timing. 30 ticket sell price seems to be the soft bot floor, but if these low numbers hold for another week or two I could see the price breaking through that soft floor, so I will be holding off on this card for now and watching the price very carefully. I'll be sure to include updates over the next few weeks.
- Nylea, God of the Hunt is extremely cheap in comparison to some of the other mythics with similar play quantities in Theros. Once rotation hits there may be a larger correction for this card, especially if mono green numbers climb.
- Pack Rat is seeing large numbers, and just starting to climb on some bots. Due to the very inexpensive entry point, I'm going to pick up a few extra copies and cross my fingers. This could be an easy to put your bot credit to good use.
- Scavenging Ooze held the #1 most played rare at one point and is now #38. It does not look like Standard will be driving a price increase on this card in the near future. The card is still seeing decent Modern play so it won't be a bust in the long run, but if you don't feel like holding onto these for a long time it might make sense to ditch them for something with more immediate potential.
Conclusion:
I hope you enjoyed this week's article. Next week I'll be focusing on what it takes to actually harvest online data in the automation section. For the speculation section, I'm not sure yet. It might make sense to just analyze standard for 1 more week in preparation for redemption. If you have a strong opinion let me know!
Great work! I have been thinking about the THS mythic rares and whether they might be worth buying in the short term. This is very helpful.
This info is very useful when it comes to decision without not enough idea of what’s going on daily on Mtgo! Great job on explaining your process to us.
I also think it’s time to get some THS mythics, I also like Stormbreath Dragon as a pick up.
Concerning the rares, i would certainly wait 1 or 2 more months. As seen for ISD and RTR prices for rares seem to be at their lowest in December. And I have been caught several times in the past buying rares from a 1st set too early.
Great information. I don’t even play MTGO, but appreciate this kind of solid data-mining. I would request you add columns after “Standard….Previous…” with a – or + (maybe red for negative and green for positive) number to show the difference. It’d just be a nice touch that would make it easier for people to look at a card on your chart and know immediately if it was trending upward/downward…when all the columns have the same color it’s easy for your eyes to jump up/down a row…
Nice idea, I’ll see if I can do that next week to help make it more visually appealing!