You either keep two counters for wins and losses or you keep two counters for wins and visits (what you call "tries"; I'll stick to the names I'm used to.).
Your UCB1 formula seems to be completely messed up. It should be something like this:
UCB1 = (move.wins + 1.0) / (move.tries + 2.0) + explorationRate * sqrt(2*log(totalTries)/(move.tries+1))
Now, the idea of the virtual loss is that you increment move.tries right after you pick the move. So while this thread is running the simulation, the other threads will see the statistics as if the result of the random game had been a loss. This doesn't guarantee that they are not going to pick the same move, but they will be less likely to do so.