Bitcoin Forum
December 05, 2016, 12:45:20 AM *
News: To be able to use the next phase of the beta forum software, please ensure that your email address is correct/functional.
 
   Home   Help Search Donate Login Register  
Pages: [1] 2 3 »  All
  Print  
Author Topic: Satoshi Dice - how to last longer  (Read 19637 times)
organofcorti
Donator
Legendary
*
Offline Offline

Activity: 1946


Poor impulse control.


View Profile WWW
July 21, 2012, 01:00:11 PM
 #1

After this discussion with dooglus about the probability of 'n' coin tosses in a row, and then watching a forum member getting excited abut winning on Satoshi Dice using the Martingale strategy and subsequently losing it all, I thought it a good idea to present a safe way to use the Martingale strategy to minimise your losses, and play the game for longer.

This is not an endorsement of gambling, but a way to gamble more safely and longer. The method does not guarantee a win, but it does make sure you're less likely to lose more than you'd want to.

The basic idea is to determine the number of times you want to gamble and the maximum amount of coin you can stand to lose. Then, using the probability of a win for the game you're playing, calculate the starting gamble and multiplier which will allow you the best chance of lasting the number of bets you'd like to play.

Here's the strategy:

1. Choose a game with a particular price multiplier to play. Let r = the price multiplier
2. Let total number of times you want to make a bet on this game = "bets".
3. Let maximum amount of coin willing to lose = "max"
4. p is probability of winning the game you're playing, q is the probability of losing the same game, q = 1 - p
5. Let the amount by which you multiply each bet after a loss be "m", m = 1/(1 - 1/r)
6. Let expected losses in a row be "n", n  = -log(bets*p + 1)/log(q)
7. Let "init" be the ideal starting amount to gamble (in the absence of transaction fees and 0.5% return on loss = max/sum(m^(1:n))

Generally, transaction fees and return on loss have little effect on the strategy. However, if you would like to take them into account:

7. Let "init" be the starting amount to gamble when taking account fees and 0.5% return on loss,
init = (max - n * 0.0005)/(sum(m^(1:n))*(1 - sum(m^(1:(n-1)))/(sum(m^(1:n)))*0.005))
8. Calculate:
 (1-(init*m^n*r - 0.0005)/(init*m^n*r))*100

This is the percentage of winnings lost to fees after an expected win (after n losses in a row). If this is too high, choose either higher max or lower number of bets and try again.


Warning: This strategy will only prevent you losing more than a maximum amount in the same order of magnitude as the one you selected. There's a lot of variance in the game, and sometimes you may lose much more - especially if p > 0.5 or your maximum is large. It works quite well with small maximum btc amounts.

For example, playing a the price multiplier = 8x  game, wanting to bet 100 times and wanting to lose a maximum of 1 btc, not taking into account fees or returns on losses:


1. r = 8
2. bets = 100
3. max = 1 btc
4. p = 8000/65536, q = 1 - p
5. m = 1 / (1 - 1 / r)
6. n = round(-log (bets * p + 1) / log( q ))
7. init = max / sum( m ^ ( 1 : n ) )
8. % fee loss = (1-(init * m ^ n * r - 0.0005)/(init * m ^ n * r)) * 100


then
m = 1.142857
init = 0.009294345
% fee loss = 0.04653956%

As above, with fees and return on loss:

7. init = max / sum( m ^ ( 1 : n ) )
8. % fee loss = (1-(init * m ^ n * r - 0.0005)/(init * m ^ n * r)) * 100

then
m = 1.142857
init = 0.009241403
% fee loss = 0.04680618%

Below are some simulations of martingale betting on Satoshi Dice using the strategy  outlined in this post. They show the usefulness of the strategy when you use a low max, as compared with the standard nightingale (start with 1btc, double each time you lose).








Bitcoin network and pool analysis 12QxPHEuxDrs7mCyGSx1iVSozTwtquDB3r
follow @oocBlog for new post notifications
1480898720
Hero Member
*
Offline Offline

Posts: 1480898720

View Profile Personal Message (Offline)

Ignore
1480898720
Reply with quote  #2

1480898720
Report to moderator
1480898720
Hero Member
*
Offline Offline

Posts: 1480898720

View Profile Personal Message (Offline)

Ignore
1480898720
Reply with quote  #2

1480898720
Report to moderator
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction. Advertise here.
dooglus
Legendary
*
Offline Offline

Activity: 1988



View Profile
July 21, 2012, 05:38:53 PM
 #2

Nice post!  There are a couple of things I'd improve about it, and since it's a quality post maybe it's worth fixing/clarifying the OP:

2. Don't use this strategy for games where p > 0.5

Define p before using it.  I'm not sure if it's my chance of winning or losing at this point.

1. Let number of rounds  you want to play = "rounds"

In the previous thread, you were using 'round' to refer to "a sequence of plays ending in a win".  I think now you may be using it to mean "a single bet, win or lose".  Is that right?  With martingale betting each round (a sequence of plays ending in a win) ends with a net win equal to your initial bet.  (-1 + -2 + -4 + -8 + 16 == 1) so people may have a target number of these kinds of rounds, giving a target net win.  Or they may have a certain amount of time, and so a target number of bets.  Best to make it clear which you're talking about.

4. Let the multiplier each round after a loss be "m", m = 1/q

I think I need to multipy by a little more than 1/q to recoup my losses.  If the house edge was 0% then multiplying by 1/q would be enough, but it's not.  To keep the net win the same whenever the win happens, define m = 1/(1 - 1/mult) where mult is the payout multiplier.  This still ignores the fact that you're paid half a percent of your stake when you lose, and are charged 0.0005 BTC on every payout, win or lose).
[/quote]

I have only one coin to spare and a days to spare

organofcorti
Donator
Legendary
*
Offline Offline

Activity: 1946


Poor impulse control.


View Profile WWW
July 22, 2012, 02:30:47 AM
 #3

Thanks for the comments, dooglus - I always post too late (after work) and I try not to make mistakes but I'm glad someone caught them.

Define p before using it.  I'm not sure if it's my chance of winning or losing at this point.

I'd originally put the warning after the algorithm, then stupidly moved it up. I moved it back so p would be defined.

1. Let number of rounds  you want to play = "rounds"

In the previous thread, you were using 'round' to refer to "a sequence of plays ending in a win".  I think now you may be using it to mean "a single bet, win or lose".  Is that right?  With martingale betting each round (a sequence of plays ending in a win) ends with a net win equal to your initial bet.  (-1 + -2 + -4 + -8 + 16 == 1) so people may have a target number of these kinds of rounds, giving a target net win.  Or they may have a certain amount of time, and so a target number of bets.  Best to make it clear which you're talking about.

You're right. I've edited the post to make it clear I'm referring to the total number of bets a player wants to make at a certain probability.

4. Let the multiplier each round after a loss be "m", m = 1/q

I think I need to multipy by a little more than 1/q to recoup my losses.  If the house edge was 0% then multiplying by 1/q would be enough, but it's not.  To keep the net win the same whenever the win happens, define m = 1/(1 - 1/mult) where mult is the payout multiplier.
I hadn't read enough about the game so I'm glad you were on the case. I'd been assuming the multiplier was was 1/p since there were fees.

 This still ignores the fact that you're paid half a percent of your stake when you lose, and are charged 0.0005 BTC on every payout, win or lose).

I should address the fees too. Why do people have to make money from their businesses? It would make life much easier for me if they didn't Wink

I'll spend some time rejiggering the strategy to take account of fees and the house edge. But you agree in principle that the strategy would minimise losses - on average -  if used? My next thought was to find parameters that reduce variance the most. Any ideas?

I have only one coin to spare and a days to spare

Fixed!

Bitcoin network and pool analysis 12QxPHEuxDrs7mCyGSx1iVSozTwtquDB3r
follow @oocBlog for new post notifications
organofcorti
Donator
Legendary
*
Offline Offline

Activity: 1946


Poor impulse control.


View Profile WWW
July 22, 2012, 08:23:02 AM
 #4

I altered the original post after dooglus' suggestions, taking into account fees and returns on losing. Anyone else see any errors?

Here's a handy-dandy calculator for the strategy, written in R.  It shouldn't be too hard to translate to python. The allbets.func function prints out a list of bets according to the strategy. Start the first bet at line 1. If you lose, make the second at line 2, etc. When you win, return to line 1.

Code:



#reports strategy parameters
strategy.func <- function(r, bets, max, p){
m <- 1 / (1 - 1 / r)
n   <- round(-log (bets * p + 1)/log(1 - p))
init <- (max - n * 0.0005)/(sum(m^(1:n))*(1 - sum(m^(1:(n-1)))/(sum(m^(1:n)))*0.005))
pc.loss <- (1 - (init*m^n*r - 0.0005)/(init*m^n*r)) * 100
return(noquote(paste("m =",m," |  init =",init," |  percentage loss to fees =",pc.loss,"%.")))
}


#reports order of martingale betting
allbets.func <- function(r, bets, max, p){
m <- 1 / (1 - 1 / r)
n   <- round(-log (bets * p + 1)/log(1 - p))
init <- (max - n * 0.0005)/(sum(m^(1:n))*(1 - sum(m^(1:(n-1)))/(sum(m^(1:n)))*0.005))
mat <- matrix(c(1:bets,round(init*m^(1:bets), 6)),bets,2)
colnames(mat)<-c("bet number", "bet amount" )
return(mat)
}

#change these variables to suit
r <- 8
p <- 8000/65536
bets <- 100
max <- 1

strategy.func(r, bets, max, p)

allbets.func(r, bets, max, p)




Output:

Code:
> strategy.func(r, bets, max, p)
[1] m = 1.14285714285714  |  init = 0.10186450536666  |  percentage loss to fees = 0.027536291774799 %.
>
> allbets.func(r, bets, max, p)

      bet number bet amount
 [1,]          1   0.116417
 [2,]          2   0.133048
 [3,]          3   0.152054
 [4,]          4   0.173776
 [5,]          5   0.198602
 [6,]          6   0.226973
 [7,]          7   0.259398
 [8,]          8   0.296455
 [9,]          9   0.338805
[10,]         10   0.387206

Bitcoin network and pool analysis 12QxPHEuxDrs7mCyGSx1iVSozTwtquDB3r
follow @oocBlog for new post notifications
organofcorti
Donator
Legendary
*
Offline Offline

Activity: 1946


Poor impulse control.


View Profile WWW
July 22, 2012, 09:21:58 AM
 #5

This is a simulator which prints out plots of strategy simulations on the left and naive martingale simulations on the right. It's long because I wanted people that are not used to R to be able to follow the code - so only a few necessary short cuts. When tunning the sim, just change the first four variables.


Code:

library(ggplot2)
library(gridExtra)
####plot functions

####plot strategy based results
strategy.plot.func <- function(r, bets, max, p){

m <- 1 / (1 - 1 / r)
<- round(-log (bets * p + 1)/log(1 - p))
init <- (max - n * 0.0005)/(sum(m^(1:n))*(1 - sum(m^(1:(n-1)))/(sum(m^(1:n)))*0.005))

rg <- bets + 1
while(round(sum(rg)/10,digits =1) != round(bets/10,digits=1)) {
if(bets*p < 3){stop("increase number of bets or change to higher payout game"); break}
rg <- rgeom(bets*p, p) + 1}

cost.func <- function(x){sum(init/(1-p)^(0:rg[x]))}
win.func <- function(x){init/(1-p)^rg[x] * r}
cost <- sapply(1:(length(rg)), cost.func)
win <- sapply(1:(length(rg)), win.func)

x <- cbind(seq(1,length(cost)*2,2),cost*-1)
y <- cbind(seq(2,length(win)*2,2),win)
z <- rbind(x,y)
z <- z[order(z[,1]),]
a <- cbind(seq(1,length(rg)*2,2),rg-1)
b <- cbind(seq(2,length(rg)*2,2),1)
c <- rbind(a,b)
c <- c[order(c[,1]),]

plot.df <- data.frame(bets = cumsum(c[,2]), btc = cumsum(z[,2]))
plot <- ggplot(plot.df) + geom_line(aes(bets, btc)) +
opts(title=paste(bets,"bets, max loss =",max,"btc, p =", p*65536,"/ 65536"))
return(plot)
}

####plot naive martingale results
naive.plot.func <- function(r, bets, p){

m <- 2
init <- 1

rg <- bets + 1
while(round(sum(rg)/10,digits =1) != round(bets/10,digits=1)) {
if(bets*p < 3){stop("increase number of bets or change to higher payout game"); break}
rg <- rgeom(bets*p, p) + 1}

cost.func <- function(x){sum(init/(1-p)^(0:rg[x]))}
win.func <- function(x){init/(1-p)^rg[x] * r}
cost <- sapply(1:(length(rg)), cost.func)
win <- sapply(1:(length(rg)), win.func)

x <- cbind(seq(1,length(cost)*2,2),cost*-1)
y <- cbind(seq(2,length(win)*2,2),win)
z <- rbind(x,y)
z <- z[order(z[,1]),]
a <- cbind(seq(1,length(rg)*2,2),rg-1)
b <- cbind(seq(2,length(rg)*2,2),1)
c <- rbind(a,b)
c <- c[order(c[,1]),]

plot.df <- data.frame(bets = cumsum(c[,2]), btc = cumsum(z[,2]))
plot <- ggplot(plot.df) + geom_line(aes(bets, btc)) +
opts(title=paste("Naive martingale,",bets,"bets, p =", p*65536,"/ 65536"))
return(plot)
}



#change these variables to suit
r <- 8
p <- 8000/65536
bets <- 100
max <- 1


png(paste("sd", rounds,max,p*65536,".png", sep='.'), height = 500*2, width = 500*16/9)
   grid.newpage()
    pushViewport(viewport(layout = grid.layout(nrow = 4, ncol = 2,
            heights = unit(c(1,1), "null"),
         default.units = "null", respect = FALSE,
        just="centre")))
    vplayout <- function(x, y)
        viewport(layout.pos.row = x, layout.pos.col = y)

print(strategy.plot.func(r, bets, max, p), vp = vplayout(1,1))
print(strategy.plot.func(r, bets, max, p), vp = vplayout(2,1))
print(strategy.plot.func(r, bets, max, p), vp = vplayout(3,1))
print(strategy.plot.func(r, bets, max, p), vp = vplayout(4,1))

print(naive.plot.func(r, bets, p), vp = vplayout(1,2))
print(naive.plot.func(r, bets, p), vp = vplayout(2,2))
print(naive.plot.func(r, bets, p), vp = vplayout(3,2))
print(naive.plot.func(r, bets, p), vp = vplayout(4,2))


dev.off()

Running this in R gives:


Bitcoin network and pool analysis 12QxPHEuxDrs7mCyGSx1iVSozTwtquDB3r
follow @oocBlog for new post notifications
dooglus
Legendary
*
Offline Offline

Activity: 1988



View Profile
July 22, 2012, 11:15:49 PM
 #6

My Internet connection just came back after being down for 24h or so.  I've not had a chance to look at your recent changes.  One thing I'm wondering about is why the losing streaks on your graphs show up as straight lines rather than exponential downward plummets.  Are you not plotting intermediate losses?

organofcorti
Donator
Legendary
*
Offline Offline

Activity: 1946


Poor impulse control.


View Profile WWW
July 23, 2012, 12:45:07 AM
 #7

Yes, that's right.I found that using a geometrically distributed random and then operating on the starts and finishes was much quicker than operating on each throw. It's just an illustration meant to compare between methods, not really give much insight to the method itself.

Bitcoin network and pool analysis 12QxPHEuxDrs7mCyGSx1iVSozTwtquDB3r
follow @oocBlog for new post notifications
dooglus
Legendary
*
Offline Offline

Activity: 1988



View Profile
July 23, 2012, 01:21:09 AM
 #8

I'll spend some time rejiggering the strategy to take account of fees and the house edge. But you agree in principle that the strategy would minimise losses - on average -  if used?

My initial reaction to this is that it shouldn't be possible to change your rate of loss at this game.  Every bet has the same (negative) expectation.  So no matter how you size your bets, don't you expect to lose at the same rate?

If the odds change over time, like in blackjack where you can use the cards you've already seen to deduce the composition of the remaining cards, you can raise your stake when the odds are in your favour and end up with a positive overall expectation.  But with SatoshiDice, like roulette, there's a constant negative expectation.

In short, you can expect to lose 1.8% (or whatever the house edge currently is) of everything you bet, no matter how you size your bets.

How does that fit in with your idea that you are minimising your losses on average?

My argument above would suggest that the way to minimise your expected losses is to minimise your stake.  i.e. don't play at all.

organofcorti
Donator
Legendary
*
Offline Offline

Activity: 1946


Poor impulse control.


View Profile WWW
July 23, 2012, 05:09:39 AM
 #9

I'll spend some time rejiggering the strategy to take account of fees and the house edge. But you agree in principle that the strategy would minimise losses - on average -  if used?

My initial reaction to this is that it shouldn't be possible to change your rate of loss at this game.  Every bet has the same (negative) expectation.  So no matter how you size your bets, don't you expect to lose at the same rate?

....

In short, you can expect to lose 1.8% (or whatever the house edge currently is) of everything you bet, no matter how you size your bets.

How does that fit in with your idea that you are minimising your losses on average?

My argument above would suggest that the way to minimise your expected losses is to minimise your stake.  i.e. don't play at all.


I guess I haven't explained my idea very well. Sorry!

The strategy's aim is to minimise the probability of spending more than you can afford while playing a number of bets. It can't affect the expectation of a bet - that will always be negative due to the house edge. The strategy's aim is to:

1. Calculate how many losses in a row you might expect for a given probability game and length of play;
2. Adjust the initial bet and multiplier so that the cost of an expected run of losses is equal to the maximum amount of btc you want to lose.

The strategy is a way to play longer, but still you'll lose out in the end as the house margin slowly eats away at your wins. However, if you're just playing for entertainment, this strategy outlines the safest way to do so.


Bitcoin network and pool analysis 12QxPHEuxDrs7mCyGSx1iVSozTwtquDB3r
follow @oocBlog for new post notifications
organofcorti
Donator
Legendary
*
Offline Offline

Activity: 1946


Poor impulse control.


View Profile WWW
July 23, 2012, 02:51:20 PM
 #10

There was an error in the strategy calculator, reported by ericrw14, a variable I hadn't renamed. Fixed now!

Thanks for the heads up, ericrw14.

Bitcoin network and pool analysis 12QxPHEuxDrs7mCyGSx1iVSozTwtquDB3r
follow @oocBlog for new post notifications
ericrw14
Jr. Member
*
Offline Offline

Activity: 59


View Profile
July 24, 2012, 03:45:48 AM
 #11

i have been using this last longer strategy for the past 5 hours on and off, and i must say, i am impressed, i have lasted way longer than i would have if i had just been martingale.
While i am positive i will lose my measly 1 btc investment, this provides enough entertainment to be well worth it. I have been testing this on the 36% 48% and 24% bets, and it has greatly extended the time i still have my money. Soon i will go into the lower dice rolls.

I would HIGHLY recommend this to anyone who would like to extend the time they can enjoy SD and its clones
TYDIRocks
Full Member
***
Offline Offline

Activity: 216


View Profile
July 27, 2012, 02:32:52 AM
 #12

Hello I'm not the best with math (I'm on 15, taking Calculus next year) and I was wondering how you got this:

4. p = 8000/65536, q = 1 - p

How do I calculate this correctly?

Amazing work by the way!

Also is a higher amount of bets a less of a chance of losing more?

Import new address/private keys with ease: https://bitcointalk.org/index.php?topic=101161
organofcorti
Donator
Legendary
*
Offline Offline

Activity: 1946


Poor impulse control.


View Profile WWW
July 27, 2012, 02:49:19 AM
 #13

Hello I'm not the best with math (I'm on 15, taking Calculus next year)
You're gambling? Aren't you a little too young to gamble?
Quote
and I was wondering how you got this:

4. p = 8000/65536, q = 1 - p

How do I calculate this correctly?

The "win odd" column on the website provides the odds as a percentage. So starting with the "Price Multiplier", (in this case 8x) look along the row until you come to the "Win odd" column. This is 12.2070%. Divide by 100 to get 0.122070, and that is your 'p'. Subtract from 1 and that is your 'q'.

Quote
Amazing work by the way!

Also is a higher amount of bets a less of a chance of losing more?

Well thank you. The actual chance that you'll lose money long term is not affected by the strategy - in the long term you'll lose by the hose odds as a percentage of what you've bet, so as a percentage of your bets you'll actually lose more. But the number of bets has little effect on the probability of losing everything you have in one run of bad luck, which risk is what this strategy is designed to minimise.

Bitcoin network and pool analysis 12QxPHEuxDrs7mCyGSx1iVSozTwtquDB3r
follow @oocBlog for new post notifications
TYDIRocks
Full Member
***
Offline Offline

Activity: 216


View Profile
July 27, 2012, 03:00:14 AM
 #14

Hello I'm not the best with math (I'm on 15, taking Calculus next year)
You're gambling? Aren't you a little too young to gamble?
Quote
and I was wondering how you got this:

4. p = 8000/65536, q = 1 - p

How do I calculate this correctly?

The "win odd" column on the website provides the odds as a percentage. So starting with the "Price Multiplier", (in this case 8x) look along the row until you come to the "Win odd" column. This is 12.2070%. Divide by 100 to get 0.122070, and that is your 'p'. Subtract from 1 and that is your 'q'.

Quote
Amazing work by the way!

Also is a higher amount of bets a less of a chance of losing more?

Well thank you. The actual chance that you'll lose money long term is not affected by the strategy - in the long term you'll lose by the hose odds as a percentage of what you've bet, so as a percentage of your bets you'll actually lose more. But the number of bets has little effect on the probability of losing everything you have in one run of bad luck, which risk is what this strategy is designed to minimise.

Thank you for the explanation. And I mined these Bitcoins so technically I can do what I want :p I only bet in small amount like 0.05 though.

And my first bet should be [1,] not init right?

Import new address/private keys with ease: https://bitcointalk.org/index.php?topic=101161
unclemantis
Member
**
Offline Offline

Activity: 98


(:firstbits => "1mantis")


View Profile
August 10, 2012, 01:43:00 AM
 #15

All we need now is a script to put this in motion Smiley

PHP, Ruby, Rails, ASP, JavaScript, SQL
20+ years experience w/ Internet Technologies
Bitcoin OTC | GPG Public Key                                                                               thoughts?
organofcorti
Donator
Legendary
*
Offline Offline

Activity: 1946


Poor impulse control.


View Profile WWW
August 10, 2012, 02:54:24 AM
 #16

Can't help there, sorry. But please do post the script (or a link to it) here if you get one up and running.

Bitcoin network and pool analysis 12QxPHEuxDrs7mCyGSx1iVSozTwtquDB3r
follow @oocBlog for new post notifications
luv2drnkbr
Hero Member
*****
Offline Offline

Activity: 771



View Profile
August 11, 2012, 08:10:50 AM
 #17

Martingale actually loses you more than straight flat betting, since you wager more.

organofcorti
Donator
Legendary
*
Offline Offline

Activity: 1946


Poor impulse control.


View Profile WWW
August 11, 2012, 08:41:54 AM
 #18

Can you provide an example? If I have made a mistake with this strategy, a specific example would be useful.

Bitcoin network and pool analysis 12QxPHEuxDrs7mCyGSx1iVSozTwtquDB3r
follow @oocBlog for new post notifications
Sovereign108
Jr. Member
*
Offline Offline

Activity: 56


View Profile
September 02, 2012, 08:57:22 AM
 #19

The trouble with this Martingale strategy is that it doesn't work as noone has unlimited funds to eventually turn a heads!

BTW, I am completely broke lol gonna have to go deeper into Satoshidice to get out haha - well at least I learned a lesson in gambling
organofcorti
Donator
Legendary
*
Offline Offline

Activity: 1946


Poor impulse control.


View Profile WWW
September 02, 2012, 09:01:50 AM
 #20

The trouble with this Martingale strategy is that it doesn't work as noone has unlimited funds to eventually turn a heads!

BTW, I am completely broke lol gonna have to go deeper into Satoshidice to get out haha - well at least I learned a lesson in gambling

The reason it wont work long term is that the odds are in the house's favour. As you can see from the simulations though, the strategy as outlined above makes it less likely that you run out of funds " to eventually turn a heads". Are you sure you followed the strategy correctly? Post what your variables were and what the outcome was, we'll see if there's an error in the strategy somewhere.

Bitcoin network and pool analysis 12QxPHEuxDrs7mCyGSx1iVSozTwtquDB3r
follow @oocBlog for new post notifications
Pages: [1] 2 3 »  All
  Print  
 
Jump to:  

Sponsored by , a Bitcoin-accepting VPN.
Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!