1101001111001111111001011001000111110110010111111110100000110010110010110100100110001100111111111100100110010000011101011100101110010010011010010111111100101000011011000111000100111111000000010010010111011101110111000000010011110100111011011101010101111011011110000011001011001110100101100001010110001011110011111011101110011101101001001011001110111101011100011111000111111101001010111100100111100001 1011111111111101101100010010010110100101010001001010010111011011100101101011101100110111101010110000011001111100001111001101101111111000100100001000111100111110001000010110001110011011110110111000110110001001101110011111100000100110101010011101000000011101100000100011000000000110010101000110110100011011000000111111000000111100011110001010100111111001010011111110010101111001110001111011110111100110 1000111000001110001111011100100110101100111001110101110011110001000011011010001110101011011110000110011100100000000100001011100110011001100001111101100100011111101001111000001101111001110011000000100011001001010100000001001000101101010100111010001000110100000101110111110111100110011100111011000111100111101011000001011110001101010011100000010100111101110111111101101101001101110001011011111000001011 0010110111100001101010011111100001110011110010010110110001110111110101110111100110110010001010100010100010000000001111001001010010001011111101101111011110000001111110001011010011110010010101010100011111001010011001110100111110110010010011110001000111000000101000111111000110100100010111000110010001010111100101011010011001010001010110001101100000100111101010011000010000000000100110100000100010101001 0111101010111001010111110101011000010010101100100010111000101101000111010111100001111010010101000101111101111110000010000110110111011001111000100101111011000011111101011000000100011111110000101011110101001011001010100101100100100011101000111100000100000000111010000000111011111100101110100001010100100111001011111111111111100100011111010110011100010100000110000111010111001110101011000010011101010011 1111110100100100101001011010000001001100101101100100010001101100100001100110110001001111101110110001000000010001110000100000101000110011110111100001000100000100101000101110001010011110111011101010110001010111111100111101100011110110101100011000101100011000100100001100100111111011011101100000111100100111101001011000100101101011100001011100010110001110001101111111100111000011001001101101001001011010 0011100001010000000100101001011110110010100010110110101111111001011110101110011010001001011000001010111100110011101010010010110101110010010110100100111100111110011101100100011110100010000110010010000101001111001010011101100010110110100110000101011011010111110101111011100111111101100101111000111100100011111000000010111100111001101011010111010011100100001101111000100000000001100001010011001100101110 1101010111100010011100111001010100010110110111001011110101111111111100111000101000000101001001010110110110001001111001010001011000000000001011101110001100111110101101111110011001000111100011111011110011010001110101110100111001101110111100011100011100100101110100101110010110011000110001011001111110100101101110010000001100100100111100110000110101000000101100111110101110010010111000100000010000110111 1100001010100011110100101011110011101101101011010010001111100111111010001000010000111010100000100110100101001100010100010011101001111101001000011101101100111001101011101001101110101000011010001010111100000011011010000100101001000000001101111100010010010110011110101000111000101001011101010011001101011011010100100110011111001111000011111001000000000010001011011000111101011101000001010101011111110011 0101110011111100110011001110010111101011010100110001000110001000111111011000100010100011000010001110101001000000000100101110000001001001100110100010001100101001101100111110011001110000010111110001000011010110001111000011001000101100100111110110010110000111011000110011000101001101010111110001101001100110100100100100101001010000101110001000001001000010100000010110110111100111011110101101100010011001 0100010110011000000010001001000110011100111001100110001010000010001100111011011111010011111011011000000001101000110011101100100000101111000110011110110010111101010001111110011000101100101011101110001100010000110111011111010000101111111011101011101110111000010001010000001010011010011101011011101010101100000110111011100001010101111011110111011011101010011101101000011011110111001010101111101100111110 0000101100011010001001110100001110110101100100011101000110001011100000110111000011100110101011110001100101101100101011010110100010001010110010001011111011111011001010111001111101101010011101100001000011100011011111111001011100111111101000011101011000000101011100110111001100001110011100111100011011110000010011110101001100111111010001101001110001110101000010011011001101001111100000110000001011100010 0101100001110000010011001000101101011101101010010100111100001010111000011010000011001101101111001000101011111010001000100110011110011000100010101010101011111010010000000001100000110111001111110011100000100111100111101011100011111010111110001101100110100101110011011111111001011101101110011111110000001010101100001110011001100011100011100011110000000111111001001100111000010111100100001110011111101100 1111011010101101000101100111110100101101001100101000010000011110100101110011001000000010010110100110010010010111010110111101101010001100101111100101110001111100010000010110001111110100011110110010101000000010101111011001011100011110100001011111010001010111101111010101100001000011010101101001001010010110101111101011101111110111110011111011000110011011011011110000011111101001011110111100100101010111 1001000010100000101010111100011110110111000111111010100101001010110110010101110101010101100111011110010110100000111000110100001101010111111011010010100111101011010100000100101000000111111010111100101110100111000110000101111111111101010000011111101110000011001111001101001100000001111010101001000100001001111000011100010010011110111110100100101110000011001010011011010000010100110110100101001011001010 1010000100000010111001000100100000000011100100101100100000100110001000100010110110100000110100111111001110100111010110100101111110001111100011101110000111010101101011000001101011110110101001111110110000110001001011111010101010001111000001011111100110010001111001011101111000101011001100110001111100001000001100011010001111110011100011011110100101010000010000110111110111010001111111110001110101010111 0001100100010111100111110110101001111000110101110000110001001011100100001101101110001000101100011000011111111000100110010110000001111000110101011110101001100111111110101111010111111100100110001110111011110001000111011110001111101111110011010101001011000110010010110100101011011011010111011001100111101000011000111011100000000011000000001011110001010110101111011100011000111101101100110110110010110101 1000000011010000100001110010100011001000000010101111001010111101010001101101100101011110101101111000011011001010000001011011000011100011111101000010100001000011100100110000111101000100111100001100110010101111100101001110000100000111111101101101110100111001010010011000011011111000100111101100010010100100000100111001001010111101110111100011110110001111001011100001110100011110110110110000010010110100 0010011001010111010001001011110111110110111110101000011010001000011001100110000101101111101001100101100001111111000110000011001001110100001011110001110111100100011000010000000100001001011000001011000010111011001010101110000110011110010010101100011010011110101101100101000001100101011010111010000101000110011110011001001111111111010010101110000110010010010001111010110101111100111110001000100001001001 0111011011110101101111010111100001001000100110001111011111011011000110010101111001111000011001110000110101101110111011110011011010010110011100000110101010000001111011010111111100110011101011101011010101110100011110111110001101101010111000101100010001101111111101110001001101000011100100011100000100000010000110110001110101101000101111110001101100000010101000010101010000111111000110000010001010101100 1110101110010111010100010001011100011110101100010100000000000000001011001101000111111100000101100101101100001100011010011001101000110101011100100010010100011011100000010110011100110001010101000101110000101000011011101000100100110111001000100100110111001011010111101011100110010001101111011101100011100110001110011001011110000011100000110101111100010100111100111001110101001100100000101011111101011110 0001111111101100000110001111011010110110011000110001111000000011101011010000100101011111000101011100110100100001010111111101110001111101000011111110110100110110110100111111100001000011011001000111011110001100100011111110101101101011101101001111001110000001101110010000110011101111110100010111100010110001000110100010001001010110010111101001111101101101011111101000100100000100000010100111110000111101 0111010100110011110010000100100001010011110010110100110011100101000010110111010100111000001111101001110110010110101111010000010010010010110101111101011000000010111000100100011011000111101000000111110011101100101101011111101001111111101110101000011101110011110100111001011100010100111111110110001000011001101100000100000010010010110010011001111100011010000101001100110011001001100011111110010101010110 0111011011100000110010000000001001101000110101110100001010011000000101000001001000000000110100001010010100010011001110111101000010100000001111000000110001100110100011101001010101000000100000000101111111000110111100111001100110010010111000011001010011111100001101100011011101100001110100100111001111110100000101001001011111101001110010001101000110111000011111011010101111010011010010011111011110100100 0001110110000100000101100011011101110101110001011111011010001011100111101100101010001101001111010101101010011011110111010110101111010101010010010111100101101000000010000010111110010000101100011110100010011111100011111000000100110000011000111111110100001011101110000111110011011001100010011000000101011000011110110011110000100010001011111001101100101110011010001011011001000100001110010010101000001101 1010010100111000000111111101010100010010010111011011010000111010010100111110010110000101101000010110101010010100111010001000001101000100110101101010100011101010001000100110000001001100111011001001101001010000010010110011100110110101001100000010111111011110011111110111011011001011110001110110111001111001110001101000100110111100101000101001011011000111111111101101010110101010000110110111000111001000 1111011100111100011011001010001101111001000101011001110010010001101100101100110010110110101101010100110111000100001000011001101001110100110110100100101000111011111100110000001011000011101011101100001111010101100001111111110001110110111101011100001111100000011001111101100111010011110001011010010101101101000010100101001111111011100000001011010000000000000101001001110011100111110011111110111100110110 0010010000011000111100000000011110100100000110011101010101011011110110011110010010010001101101011101110110111111000011001111111010001010101101010010101101001100000111100000110001000100010000110110011000100100011111001000011111111000010110011010010110101110101010111001000100010111100010001000010100000100001001011100011110111000111010000000101101110100000101010001001111100000011001001101001110000010 1000011001100100001001111011000011001000000010100001100111110100100111011011000010101011000011000111101000101000100010100100001011001100001000011011101010110011100010011111100010111111010000011010100000101110000000111000101011011111100000100000110110101111101010101111111100100000001010011100100001110000100010100101010100000111100100001010110101111010011101101000010100111000000000101010011001000101 1010101011010111110101110100110100110111010100111111000100110000000110010011010110010111111000011011110100101000011001101010100111101000010000100001001000100000001101100010101011010000100100110111111110110110101101011110010100100111001110010000000100111000010111010001000111000101000100010001011110000101111001110111110110001100111000011000100111001110000110000101101101011100010111111010100001000001 0100011100001110111010000000100010110011000010000010101101100010110100101010101100001001011110010111001000101111011111111101110101110101100111100111000000011110010000010101110100111100100001101110100011111011100100010001101011000011101101100001010011000110100110100010011111000111111101000011000011111000011110000111110000001000100011100000001000111110100000101000010111100011110011100001111110000011 0001001110010110001110011011111110111101101000001011101100001000011101011001111010111010111011101011011010110110001110110000001101111001110100110100000101100011111111111110100000010010111100000110010110110010000100101010001111000110111101011100110111010110011000011000011110100111011111011101111100011110010101010111100011001001001110011001101011010111000001000010110011000100111110010011110101100011 1110010001100011011011110010110000011010100100100111100000010000011110110110000000000000111100001111100110001110000111011000111000111110000111100010010011011000001011001101001010000010101110010001011010011000110111000000001100011011111100001010111000101110010110100010010110010000100111101111100000000011011100001110111100111011011000110100110101000010000001011101010100101000011001000000000000100011 1100011111000011100100010011011000100000001001001010000000010010101010110111010110101110011111000000110111011000001001110110001001011101001001100000010110010100100001000000110010100011011110001010110100001100111001101111001001110010001110000101001111110001101001101001001001110100000001011011000110111010101001101110100111100101001001011000100011001010001110010101001001010110101100000011101101011111 1101100111010111001111000010111011011011111110101010101010001101101110001010011000010101010010010000101010100100001011010001101001001000110001001111001010101101101000010000000101110101100101000000101010100110010101110101011110111111111000110111001100011100110001100110001110010011110001100010001100010010011101110101001100011001101010111000001001000010100001001000010110100001110000011110111001001001 0011101010010011111000011111011000000111010110100100100101100111011001010101101011101111010110000110011010010100111001010110010111110110100100110110100101110101011010010101000110111100100010111000101000111101111101101111000110011001100011111111000110001001010000011000100100001001000001110001000000001111001001000100101101110111010111011001011101101100000100011101111001100011110001100010001100000100 1110011011111000000111011110001110100110011111100000110000000110101100010011101111100010000101101111111010001100001101000011111001010001100000100100111010101000111100001111110000001001001101101010010110011110010010001100001111001000010000111101011100011100010011011100000100000011101001000111101100000100110111111111110111011001001101101100111001100100111111111010101000010001110010111101111110111010 0000110100100000010100010011110001010010111100000100100110100011101001010100100010110100111110001001001110010011110010111110011110100010101011110100110010001100111110101111101010010000010011001111011010000101100110111111010000001100011010001011101001101110000010000001001000010001001011100110100000101101001010011000111000000010000011011010111010011110110100001101110011001111111100111000100000000110 0001100011000111111010100110001011000001100011010001101100010000001010111001100100000000110111110110100011010111101011111001110010110111111010000110100010010110110110000001100110000111100111101000111001111110000110000101100101000110101001001011110111101110000101001011010111011100101000011001001100111011001111101011010010001110011100101111011010001111101001111101010001010100111011100011011100001100 1110010000110111011011000100110001011000001111011111101100100001101010110000100110111011001001001100000110100110000100000100110101001111000000001000100000100011001001100011100010011000111011011010010101111110100111000010010011101100100000101111111010000001101001101000111010101010011010111011100101011010011010010111011011011101101110111001111001011011100100010110111010011100011011001000010001000011 0001100111101100101010110011001111001111110101111101111111010011101010001001110100101101101000000101001010000111011001101001010101110100001110011010100101111000010011001001010010010000100011010111011010100100101010110101010010110110010110010110010100001001101111011111111111100010011110101010011000010000100000011001110011010000100100100011111101101110010011101101110111011111000101101111100011001011 1010011100100010111001010110100100000110011001100001001001101010110101110011101001011010011010001010110110001010011000100111011101010001011101111100000101110100001001100110101010111100100000011100001110000001110110001001110110111100000011000110110000010100000110010001111101110111001101110100010111001110110100001000001110111110101110111110101101001110111110000110001011001000010011111001100010111011 0101000111011100100100011100100111111011111001001000010111001001011000100010000101000101011100010000011110000010101111010010110110101001101101110000011101010010001000100111001100110010101111011111101000001011000100001101111011001101100011111000000100011101100011111100010011101101100011110101011010110010001001000110101001010011010101100010100100011011110100000101000011000001110100010000101000000001 0101001111101101001000011010011101001010001111011011010010110111000100111011101001100110010100010101111011001101111000010001110011100101100101100011010111000001000010111111111000000001101000101111110010010001110000010110010001100111101000011100100000100000011000110101011000101101111100011111101111010101010011100111111100110011010101110010001110110110001111101011111111011111011011010000011110100111 0111101001001001000001110111010100101101111010100110000011010110101110010101001001111000101010101010010100100111001100100000011000110100001111010110000011101100111011110011100010001001101100001111000000110101111110100010110110010100110010100101100010000100011011101110111010000110000011111110100011011110100111001000010001100100010010101100110111111110011111010000010100001011010101011000101110010011 1011010100010011001100011100011011011110110000111000111110000111110100011000110010111101010001010111111001010101111011000110101101000111101011110101111010110011010100110001101110011011000010001101111110011000001101101100000101111001100100110000001101000110000111000000000001110000100000100100000110101011101101001111111010100000010010011001000001010001110011011110001101101000100001101001110011111010 1010111010011001011101100010000010001111111010000111001010101011000100011000001011011101101000010111101001100011101001100011101101110010101111111111011110011100000100100011101011101010100110100101101010111111001100111011011100100001110001111101111110111000101000111111110010110011000111011101101100001011000101111110100001110011000000101111001000101000010000010111000001010110111010011000101111111010 0000100100111111100011001110000000100111111011110000110011001100100111110101010011101110001011010001001000111111010000111110110000011100010011010001000100100010000001010000001000001110001000001101001000111000111001111001000110011011101001000100011010010101000110110010100011110001000110100111111001111100011110011100000100001001110011110001011001001111111110110010000110000000000110100110010000100110 0010111110100100000110011000000100100001011010010010101001001010101010100100010101000100011010000011110101101001010010010110101111001010011011000100110011001000011010011100001000111111010101001010110010001000111000010101000011100110001100001101010010011000011100011111010111000000110101000111011110001011101110010111011010010111011100111101001000011001101100001101101000100100011100101101100001011010 0111111011100100001101100010010110011010110110101100100001010110010110100101000010110001110101100111111111101100001001011001110001100111000101011011100110000111010001110000001011010111010101111010010110001110001100000100100010110111101101011101001101101010001001010011000100011101101111111010001110110100100000001010100001111011101110101010110010001110101011110110110101111011011000011111011010000010 1011001011010010101100101011111000000100110010110111000111001010100111101111001100001100000000110001111010100000100000011010111011001111101111111000101010110100011000111100110100000001010111010101001010101001010110001101011000110110110011111110110001001000110101110011110110010010111001011000010001101101010111001100001111010101011100110000000000100110010000001001010101001001001101111011010100000011 1011110010100010101011001001101101100011001001001111100001010111100000001000001110001101111100101111001111010101100111011001011111001001100001011010111011010100100011101010001101100000111100010110111101001000000100111011101100001111011110011010111100011010011100001110110100010100110010101010000101100111100010010101001100111100100010100101000011110011010001010001001110011111110100000000011111001111 0111111110101100100110111100011111100101000111010000001001010111101010100001101110010101011011100100010011010111000101110010001000000010100101001100010011011001010000000001110000000100111000100001000011100111101000110011001001110110101000100101101000110100001010010100101000100100101110111100100110011111011111001010101000010100100100011110111000000010111100101111000010110110100101001011101100111111 0001011000001111011001100001100101101110101100110000100111111110111011011001101011011101011110101110100101100000000001000110000000111101110101100100011011111111111100011111000000101101011000000000100011100101000111010001010010101101001010101001111100011100100110100100011010010101111101001110111110000011001100010101110000010010010110011110100100100101011110010110101010110000100011000100101010101110 1011111001100101001110111001100101010000011110010010010111000011011100001010011100011100101000100001111100011110101010000011101100101000100001001000111010111011011010100110001001110000100101111110111000110101111000110101110000001000000000011001101110110000110011010010001101001110101000111000000001010011110011001001011011111100100001000110000000011100111001100010001011011100101010000010111101110110 0110100011000100000010101100100010101100000011010010111000010100010100000001001001100010011110000011100001101001001101000101110001111001100100101000010001100010110011000001000101010101110101110100100000100000001001000000010001011000100101111101111010111011111110111001100000110110110100100110100000100100110000111010110100000110011011100011000000000000011001111111100101100111000001011111111001110111 1100011100111001010011101011101100110011110110000011010001110010100101001110101100011110000101100000000101100011010111110111010011001111110001001101001000011100100100011011111100011111110011000001011011101001101011011011010111110000110101001110100001000001101111110101001010110101011110001111000001011111001010011110110110010110000111010001001010100101101111101001101110011001000010111100101101100110 0110000011010001000110010000100100000010110001110101101001000011000010011000010101000011100001000000000101011010111111110001000000101010100010001011111001011101010111010100111011111110111110111101111101011101010010011100000110010010110110010101111111111000101100100010101000100100111100111111000001001111000000101011000000101111111101101111001111010110001000011000111110001101101000100001001000101110 0001110000100100100011011011010101111111001100110110001101101101001001101001101001100000100100011100010001010011101101010100001010100010000110010000110010000100000000000110100010011010011010100101110010111100110001111000001011011010010001001110010001011111010110000111110101001010000010110110101001111101001001111100011110010001001111100011011110111000111001001000000010010100100101111001001110011000 0000110101101010000110010010110001101001000000100100010011000001100011100101111100101101001111010000011101010010010010111101111110010100111101000111011010100000001111000110011110000011011110000001100010000110111001111100001011111111101010011000000111001110000110011001111110110001010110010101101100000000100011100101001101000001010010001011101010011010101000010100010100010101100111001010011111000010 1011100101101101010100011110011101001101111010110000011100111001010010100000000000000011100011000110001101001011010100111000101000000010011111001011001100001010101000010100000001100101100011000100110010000101100100111110110100000000011111011001001101010111001101010100010001100101011000010101000001011111100110100011010100110001101111110010010000111100010000111101110000011110010100000100110010100010 1110000011101001110001010001100101111001110010111111000010100011001010100111000111001000011001001110010100001111000000000101011100100101100110100001010001110011111011100101110011000011100101011011100101011100011110111011001011111001111101101110100010101101011110011110100111111000100011100111001011001100100011001001111100011101011010000001100111010100111110110110001000100111010010110010110110001011 0101101000011110100110000011111110110001000101010111100100011011001000100010000110111110011100010111011001011101010000111000110101011111100001100100000111110100110110101000101100100100110000000000100011011010011110010001110001101001101011001010111101000101000101001110000000010010101001110000010101011101011001110010001111111001111101110101101010011100111111001001000010101110100011001001010001011100 0110100001010000001011100101100110110100000010010101101110001001011101100101001111000010000001111101000100111001110001010001100111100101011100000011100000010000000001011011011110001000110100000000111000010011111011001011001001110100001000111101100110101010011000111001011000101000110110101110101001001101111110111010000010011011010111101011100110001111001110110000111001100011110010000000110101011101 0001110101000111110100011010111010111111010001010101011001011011111101010100010100000000010101111101000101100001101010100100001011100000111101001101000010100001111000010010010100101110010001000011111011100100001001101011000101101000011110001101000101010100011011001100100101111011001101011011010011100110011000100101110110110101111111101000110110101001100100110111101111100111000011000101001001100100 0001111001011010111101101000101101110101010101101001100011010000011101001101010110100101000111111100000011011101010000111111101111011000001110011101110000101100010001010100001101001001111001011000111000110000000010000111001100001000100000010011001110111011111101001010000000001010011000001000111101110111101111000000100001010011111000111000010100111011100111111000000000010001010110111101011001001101 1000110000100000001110101111010110001111000000001101110111011111110011111101111100011101100011001000001000110011000100110000010110101111000111111101011100111100001111011110011111100010100001011011101110000011000110100000111011011001100011010000110011100001111111001110001100101110011111100010101001001101001100101010111110101111000110011100010010011111101111111010011010100110000010011100010100111001 1110001101101111011001101011000011000001101111111100010011010010011001011101010000111111100000001101111100101100000111100100001011101011101010011100110100011001111011010110001100011011101111010011111000010001010100011000001011110000001011011110010110000010100101000110000100011010110100011111001001010011110010011011010011110100100010001110111001101001110111110001000100001111010111000101011100110000 1111010101111010001010110101100111001000010101010010010000101000010010110101001111001010101010011101011000001110111011010010100110001100111101000011011110010111010001101111000010101100100101000011010101000010011010010000111010110001001110010111111110010011011000110010100010100011101000111001100000100010001101100110000101111000100010010101010111010000101010101011010101011001110010111011000101010110 0111000000010110011100110010010111001010001100010010001111111011011101101000001110011011101101000010011000001110001010101110010010000111000101110110001101111000110011010001101110011011000101100011001110001000010110011110011101001011111110010001001110011000001001110010010111001101101100110011110101111010101100010010011011100101010100110011110001001101001011010110001100100010101001011100101001111001 0011101010010010101010101000011111001001100111000010110110100011001101110101111101000000110001101101110101111110110101000000100100001001011011000011100101010110010001101000111110011011000101011001111110110101100111110010100011010000000000011111111110010000010111010101010101110010110101011100000100100010011101000111010110010101000110101000110010101011100110001000111110011100101010100110101101100100 0010000001111011000110111010010100011001011000111000000011000100111010001100111010011011010100110111100101100111001110011010110101011111000100101010001001010000100110001000101000011101111111001110000001000010111000111101010000100100001100011001100111011111110010110010101001001100011010000001011001000101100100100101000010011101011011011110010011100101000000011110101100001111011100010110010000000000 0000111111101011110001110101101010110001000011111101000111010101010011011001010110110000110011100101001100110110000010110010010010011001011011001111110101011100001100101000011011010100000101011111000011100110101100111010001010111110111000000001001111000001001001100111010010111011011010010011110000101010111001001001011101010111010011010110111001010111100101000000110011000001110101001010100010111110 0110100001110000011000000111001001000100111100000011100100001011000000111010110001011101001010001001100110110010001101001001011000101010110100111000110000001010011101100110101100001010010010000001101111000000100110011110111000111110100000001001011011100100101001010011010010011100001111010100101101101100000010100011000101101110101111111011110011001001000100100000010001101001001110101000101100000011 1110010110000000111101011111001101000000001010110110011010111111111010111011001000110111001110111010100110010001101000110000101101000110111011010100001100110001111010110101010001011001001010101000110001110100000110100110101001100010110010101010010101111101001000010010110000101101111011110100110000101011101011000111111100110010001000011101110011111110001100101100011101111100000110001010000101110101 0110101001100000010011001010001000011000001100110100110000000100111011000001000101000011101010110010111101010111010101010010110000111010100000000011111010110100000111000001010110010000001001110101101111000110110110101000101011111111111000111111011100110100001101110000100010111110100100111001100000101011111010110111000110111101101000000101000100111101100001111010000101001001101011000110000110000011 1111111111100101111111001101000101001000100011100101101011001100011001110011000110100000101101101010100010011110100111101101000000100011001000011100111001011111110100111000101111001001111000011000110000110011011110011011110111100111111111010110001001110110110111011111000111010100011111111100001010000111100010110101000110000010001111010111111011101111010111101101101101110101000011110000000000000001 1111010011111100010001100101011101100101001111000110110011001110111010000101100101010101010001101001000001110101000000000101101010010111110100011010100101010000001001010101010011010100001011000001111111101100011111000010001010101100001111101111011100011101011010101101101011110001000010111001111001110010001000010100001011111011011001110101111010011100100110001011111001101100110011000111011101001010 0110100111101101100001110110001111100110110100110011000100000100010001000111001001001110100110111100001111100111101111010001111010001101101100011000001110100001011010111001101000010010100101000010111100010000001101100111011000111011111100000100101111101111001111100000010000010001001100010111110111101101110001110010101000100011101010111110010000111111000111011100001000000011110101010011100010010001 0100010100110011000101010111110101101011101010001010010001100111110000010010000011101111001001011101000110110100000011010110111100001100110101100000100001011000101001000010010001100011100110001011001010010000111111000011111010101111000010001011100000011110111011100100000000111001010100000110111000010010111111111101111000000011010110011101101110011110000001110101111101100100011010001001110110110111 1001110101010110111111010100111001101111011101010101001110111101100010010101010000100110110001101100000101100110110010010101001001101100011010110000110010011010100000000010100100101010011101101000011010010000100001111111111110011001101011101100100000001110000011010011000011000110110001000100100101101100011100101110110001000011010011110111111001011001001010111000011111101001011000100101111000110101 1110101001000001000000011011001011011001001011000001011110000000100111000000111000100111001001001011000001100011001100001011000111010000110001110011100111011100110010111110101010000000101011001100010111000001000000000101000010100001110001000101111010101010100001100110010001101011011001001110111111101010011101111011111010110011110010011110001111000100100110111110110110000010111011000010011101011111 0000111101011100000111110011010010111110111001101001000100110001010101011100010110010100000011001000111111000110110101100011011100100110000110001110000010001111100111110110111100000110000000101100000101001101110010100101100000011101100100110011110100001100001111110100110111101110001010110001011101110011000011001101010001111110000000101011100000110000001101101011001000000110000000111011110011101011 0101000010000000000000111001001100110011100000001001101100001111111100010101011011011111001000010100000111001010001011100010001000101000101001010010000000000011011011001110100000010101110101011001111000111001011001110110000101111100101011011000000001100100101010000011001100101001110010101001010010011001001010101111111011100011000110000100101001110111110111000001001010000100101111111011100100111101 0010100000110000011111100101010101100100100100111010001111111111101011001111100010010111000111101011010001111001100000111110110011110011010110101100000010101110000111000011100111001111001111010001000001100110001000011000011100011111111101100011000000010010101001100100010000101100010011000000111000000000110111100011111110010010001010100000001011111011010010001101011011110010101010101000111101100000 0111001101100110100011100001011011100011100011011001110110101100001001011100000101000010011001001110111000001101000100001100001100111101100101110011110010101100011001011100101100100100001011011011110010101011101010000101111010000000011100000000010001011001000101010000010001011010010101110001010101011111010100010101111000111000110010011111000010110110011011101111001000100001010111100100110101000110 1110010000011001000100000011011101110001101100001101010110010101000100010010100100010100101101111100000110001111011110000101110010001000000010001101010100011110011000100001101001100001010111110110000000000001111101100000110111000100111101110010011010000010111000101110111111011010000000100001010110000101000010011100001010011110000111000010000101101001110010101111111011011111101010010011000011110010 0111010000001110010010011100000000100001111101101100010011000011110100010110011110111011010011110000101001010010001100010011110100000111000001111100111000101000110011001100010001001011111111100011011110101000010101001000000000111101001101011001111100101011010111111011101011100111001110001100011111011100001100101000000110011011100000011111101101100100010000010110010100110111011001010010001111110100 1110100010001000110000101110110011111001001011111100000101001101101011111110111011000011001010010111000000101011000000001010001110101011111100111000001101101000111011100000110101000011011110001101110010101100101001110000011100010111110011100100001011011111011111101011011001111101101100010011000101100001001010010101011010101100110101010100000001111001111101111101111111100111000101111000100110011001 0011001111100101110010011000001101010110000110100011001110000001010001010101110000100000111010100110011011000001100001111001011110000110011000101000011001101001101000001100110000000101001011101100110001010001011101001010100011110100011000110000111100100110011001000011001110101001001110100101110001011100000100111110010101011011000001000101011000110011001000101000110000110100011001100001100000100111 1110010111110010001101010101001011011101010001110110011001101000010111101010001111000110010111111011010101111000110000110110010010011111010111101011010101001011111011110000101010011100110011100100010010000101000001100100110101001001000111101010000110100011010101011011001000010100001110001110101100010000101101011100010001001000010000011010001010100011001001111011000100000011101011101110001001111000 1100010000010001000001100100010011110011101000000100000110010100000111111011101000101100100001000110100000100000000000101001100011100000000111000011100101101001000000111010000101101111100111101010111101110001001000111000101000110100110001000001110110001111100000100010111110111011100110111111001001100000111111011101001110110001011110110100011101010111001010101000010100111000000100010101010110100110 1111101111011001010111110011010010010110001010100001011001100001110010011000110010010010011001000100011010011100110111001000100011000011011111000100000111100011011001000011011010101000001001101110001111010001111001110100011111001110001011010010110001101011001110011010100100111111101010110001111110000011010010001011111100011001000010010011101011110011011000010000111110000000011010001101001010101100 0001101010100011101100111000100001101001000011011010101010000010111100001001111101011101101010010010110101101100011010011000011000110100111001111001010101010100000001010110110001110100010010100001101111000000111000101010011010101011110000111001001110111010101010101101101011100001100001110101110010000000000101111111000100000011100000010000110011101110101001010110000111100110001111110101011001101110 0001110001011001111110001111100011100111010001100101110001100100001011001000100011000011011001010110110011011000000100011110011100000111111010000110100010000011000010111001111010101110110101011110001001010101100111101000010000010011010111001110100010101000011101101011101011011110101101101110100111110011011100111100001101110001100111101101110101000000110001111110001010001011000001100110110111010110 1110101101100000001001101000111100010010011000100111101100100011111101010101000101110010010101110111010100100010111101001010000010000100000101110000100000000011101000100101001100011111110010000100111111111110100010100110111110000110011110010101000001111100101101110010000100001001001100000101101000001001011100101010110110000110000110011101000111111100001100001100011010101010101111110010001000101001 1110111011001011011001001010001100101001100000001001001011011100111110010101000010011000000100010101100100010101110010000001100000101010110101010001010100111111111010000111011110101001100000111010010011010110101010000101001000000110001100011000001101100011110110101100010010101001111001110111100110100110001001101010110011001010010111001111111111100010011001100010001101111011110011001001111010111111 0110010000100001010100110101110100000101110111100111011100110101011110100010110101111111011111100011101101001010010111111100111101110001010001111011000000101100111001011011011100001100111001001101011111001010001000011101111011110011000111100000000100101100010110011110010000100010011110000011000111100100110000011001111011101010011011000101000110100011010100000110110110111100111011010010000101000111 0110110101101111001111000111010010110010000110110000000110001110010011001110000001010110011011111000011000101011100011111101111011101101100011000110000110011110101101011100111100010110100011011110010101000001001011101001100001111000100110101110011010001010001000111001111111111111110101011101011000100000110011101001001000011010100011101110001001110111100011010010101010010100011011101100000010101000 0100011011101001101010000101000011001001100110001010000011001001011010000010101000010111111101100101001111000000111111001100000001100111101010111001100110100101101011010101101111101000100110010010010000011000111011000111101101101111110110110100010100100010101010101110110001001011110001000100011001000010001110111100001111001100011001101100101010110001101011000110000011100110000100111010011100110100
C#cTrader Algo

【cAlgo】cBot開発でも新しめのC#機能を使いたい!【Tips】

7/30/2021

3年以上前の記事です。内容が古くなっている可能性があります。

cTraderのcBot開発にはC#4.0の機能までしか使えない?

cTraderフォーラムを見てるとときどきこんな話を目にします。これはある意味正しいのですが、正確ではありません。

確かにAutomate画面から右クリックで「VisualStudioで編集」した場合、そのままではほぼC#4.0までの機能しか使えません

ただ、新しい機能を使う方法がないわけではないのです。少し詳しくみてみましょう。

 

C#の機能とは何を指すのか

「C#の機能」といってもちょっとざっくりしすぎてて何を指すのかわかりにくいので、ここでは2つに大別して考えます。

①言語自体の機能

いわゆるC#の新機能というとこっちを指すのが普通かもしれません。「こんな文法が追加され、こんな書き方がこんなことができるようになったよ!」みたいなのです。

たとえば文字列補完式。変数priceの中身を出力したいときはこんな風に書けます。

    Console.WriteLine($"価格は{price}円です。");

この文字列の中に{}で変数を埋め込むというのはC#6.0から使える機能です。

同じことをC#4.0でやろうとした場合、こんな風に書く必要があります。

    Console.WriteLine("価格は{0}円です。",price);

微妙にわかりにくくて不便。WriteLineで使うならまだいいのですが、普通に文字列生成したいときにはstring.Formatを使わなければならないため余計に面倒です。

実際(普通にやったら)cBotやIndicatorの開発では文字列補完式は使えません。これは実は使ってるC#のバージョンが低いわけではなく、C#4.0以上に相当する機能はcBot開発用拡張機能によってエラーとしてはじかれるようなのです。

逆に言えばこれら新しめの言語機能は拡張機能にさえ邪魔されなければ、コンパイルもできるし動作も問題ないといった機能なのです。

 

②.Netフレームワークの機能

例えばWeb接続なんかをしたい場合、現在だとSystem.Net.Http名前空間のクラスを使うのが一般的だと思いますが、cBot開発においては(そのままでは)使えません。

using System.Net.Httpと冒頭に書いてもエラーになりますし、参照追加しようとしても選択肢に出てこないのです。

「C#4.0までの機能しか使えないから仕方ない」とあきらめるのは早いです。これはC#の機能ではなくて.Net Frameworkの機能でして、.Net Frameworkのバージョンが古いのが問題なのです。

cBot開発時のターゲットフレームワークはデフォルトは.Net Frammework4 Client Profileですが、System.Net.Http名前空間は.Net Framework4.5で追加されたものなので使えないというだけです。

ターゲットフレームワークさえ変えられれば利用できる機能ということです。

 

フレームワーク依存の機能だけでも使えるようにする

先に簡単な②を解決する方法を紹介します。一応簡単にフレームワークの説明しますが、方法だけ知りたい方はこちらへ。

 

そもそもフレームワークってなんだ?

C#やVBといった言語は.Netのフレームワーク上で動きます。要は.NetのフレームワークというのはC#やVBを動かすために必要な基盤です。JAVAのプログラムを動かすためにJAVA仮想マシンが必要なのと同じように、VBやC#のプログラムを動かすには.Netのフレームワークが必要なのです。

例えばcTraderの場合は.Net Framework 4.0上で動くため、.Net Frameworkのバージョン4.0以上がPCにインストールされていないとcTrader自体動きません

「そんなもんインストールした覚えがないぞ!」という方もご心配なく。.Net FrameworkはWindowsのインストール時に一緒にインストールされています。Windowsのバージョンによってインストールされてる.Net Frameworkのバージョンも異なります。

この.Net Frameworkが色々な機能をもったクラスを提供してくれるおかげで、C#のプログラムではネットに接続したりみたいな実際は複雑な処理が必要なことが、たった数行のコードを書くだけで手軽にできるわけです。

(なお、今では.Net Framework自体がすでに古いフレームワークです。.Net Frameworkはバージョン4.8で更新が終了しており、現在はWindowsのみならずMacやLinuxでも利用できる.Net Coreが主流となっています。)

 

C#と.NetFrameworkの関係

C#のバージョンと.Net Frameworkのバージョンというのは確かに密接な関係にはあります。例えばC#4.0であれば対応する.Net Frameworkは4.0です。

(それぞれバージョンの対応はQiitaのこのページが参考になります。必ずしも同じ番号が振られてるわけではありません。)

こういうと、「C#4.0機能しか使えないのだから.Net Frameworkも4.0までしか使えないのは仕方ない」と思ってしまいそうですが、そういうことではありません。

あくまでC#4.0の機能が.Net Framework4.0までの機能をベースに設計されているというだけの話です。C#4.0の機能の中には.Net Frameworkが4.0以上じゃないと動かないのもあるよ、ってことです。

 

ターゲットフレームワークは変更できる

cBot開発で一見.Net Framework4.0までの機能しか使えないのは、ターゲットフレームワークが最初からそう設定されてるからというだけです。

別にcTraderが.Net Framework4.0で開発されていたからといって、新しい.Net Frameworkさえ用意できる環境であれば、cBotやインジケーターまでcTrader本体に合わせる必要はありません。

cTraderのcBotやインジケーターを作る場合、ターゲットフレームワークとしてはデフォルトで「.Net Framework 4 Client Profile」が指定されていますが、そもそも今cTraderが動いてるPCで.Net Framework 4 ClientProfileしか入ってないなんてことはそうそうありません

少なくともWindows10であれば必ず.Net Framework4.6以上が入ってます。ターゲットフレームワークは新しいものに変更してしまいましょう。(自分が使うだけのcBotやインジなら選択肢に出てくる一番新しいものにして大丈夫です。)

VisualStudioの「プロジェクト」メニューの一番下、「 (プロジェクト名) のプロパティ」を開いて、「対象のフレームワーク」を変更します。

これだけで「〇〇というクラスが使えない」「〇〇が参照に追加できない」といった問題は解決することが多いです。

 

 

C#言語機能の新しいものも使う方法

次に①の新しめのC#言語機能を使う方法。要はcBotの拡張機能が邪魔なだけなので、拡張機能が動いてないところでcBotを作ってしまえばいいのです。

 

C#の新しい機能使いたいなら、メイン処理は別ライブラリとして作るべし

結論としてはこれだけなんですけどね。ライブラリを作る際はターゲットフレームワークは自分で指定するため、これもできるだけ新しいの選んでおきましょう。

これによりC#7.0までの機能はすべて使うことができます。以下で手順を詳しく説明します。

 

手順

ライブラリとして作っても、cTraderで使えないと意味がありません。ライブラリの機能をcBotやインジケーター本体のalgoファイルから呼び出す必要があります。

そのため、こんな手順で作っていきます。(cBotで説明しますが、インジケーターでもRobotクラスがIndicatorクラスに変わるだけで、ほぼ同じです。)

①ライブラリ側でRobotクラスをメンバに持つMyTestLogicクラスを作る。

②ライブラリ側でロジックを実装する。

③algoファイルからはライブラリを読み込み、MyTestLogicオブジェクトを作り、メソッドを呼び出すだけ。

では一つずつ見てみましょう

 

①ライブラリ側を作る

VisualStudioで新規プロジェクトを作成します。

新しいプロジェクトの作成で「クラスライブラリ(.Net Framework)」を選んでください。

次の画面で名前やターゲットフレームワークを設定します。

名前はなんでもいいです。フレームワークは自分で使うだけであれば、一番新しいものを選んでおけば、上記②の機能も問題なく使えます。(デフォルトで新しいものが選ばれてると思います。)

あとでcBot本体から参照するときに作成した「場所」が必要になりますので覚えておいてください。そのままであれば自分のフォルダのsource\reposの中だと思います。

続いて、cAlgoのクラスを使えるようにcTrader APIのDLLを読み込みます

ソリューションエクスプローラの参照を右クリックしてして、「参照の追加」。cAlgoAPI.dllファイルを探して、追加します。おそらく PC>ドキュメント>cAlgo>APIにあります。

あとは冒頭にusing文を追記すれば

using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;

これで、cBotを作っている時と同じ感覚でcAlgoのクラスが使えるようになります。

あとはClass1の名前をMyTestLogicとでも変更して、こんな感じの雛形を作ります。パラメータを持つcBotの場合は、コンストラクタの引数にでも追加しておいてください。(インジケーターの場合はOutput属性のIndicatorDataSeriesも)

namespace MyLogic {
    public class MyTestLogic {
        // --- フィールドにrobotを持たせる
        private Robot _robot;

        // --- パラメータがあればこんな感じで
        //public int Period { get; set; }

        // --- コーディングしやすいようにプロパティ化しておく
        public Chart Chart => _robot.Chart;
        public Bars Bars => _robot.Bars;
        public double Bid => _robot.Bid;
        public double Ask => _robot.Ask;
        public Symbol Symbol => _robot.Symbol;
        public string SymbolName => _robot.SymbolName;
        public Positions Positions => _robot.Positions;
        public PendingOrders PendingOrders => _robot.PendingOrders;
        public DateTime Time => _robot.Time;
        public History History => _robot.History;
        public MarketData MarketData => _robot.MarketData;
        public IIndicatorsAccessor Indicators => _robot.Indicators;
        public void Print(string msg, params object[] parameters) => _robot.Print(msg, parameters);
        public void Print(params object[] parameters) => _robot.Print(parameters);
        public void Print(object value) => _robot.Print(value);
        public TradeResult ExecuteMarketOrder(TradeType tradeType, string symbolName, double volume)
            => _robot.ExecuteMarketOrder(tradeType, symbolName, volume);
        public TradeResult ExecuteMarketOrder(TradeType tradeType, string symbolName, double volume, string label)
            => _robot.ExecuteMarketOrder(tradeType, symbolName, volume, label);
        public TradeResult ExecuteMarketOrder(TradeType tradeType, string symbolName, double volume, string label, double? stopLossPips, double? takeProfitPips)
            => _robot.ExecuteMarketOrder(tradeType, symbolName, volume, label, stopLossPips, takeProfitPips);
        public TradeResult ExecuteMarketOrder(TradeType tradeType, string symbolName, double volume, string label, double? stopLossPips, double? takeProfitPips, string comment)
            => _robot.ExecuteMarketOrder(tradeType, symbolName, volume, label, stopLossPips, takeProfitPips, comment);
        public TradeResult ExecuteMarketOrder(TradeType tradeType, string symbolName, double volume, string label, double? stopLossPips, double? takeProfitPips, string comment, bool hasTrailingStop)
            => _robot.ExecuteMarketOrder(tradeType, symbolName, volume, label, stopLossPips, takeProfitPips, comment, hasTrailingStop);

        public MyTestLogic(Robot robot) {
            _robot = robot;
            // --- パラメータがあれば引数で受け取ってセットしておく
            // Period = period;
        }

        //------------------------------------------------
        // 下記をそれぞれ本体の同名メソッド内で呼び出す
        //------------------------------------------------
        public void OnStart() {
        }
        public void OnTick() {
        }
        public void OnBar() {
        }
        public void OnStop() {
        }
    }
}

Robotクラスのプロパティやパラメータはほとんどpublicなので_robot.の形でアクセス可能ですが、いちいち書くのが面倒なので直接呼び出せるようにプロパティ化しておきます。

Robotのpublicメソッドも、PrintやExecuteMarketOrderなど頻繁に使うものは直接呼び出せるようにしておくと便利です。(他にも必要なものあれば加えてください。)

 

②ライブラリ側でロジックを実装する

中身を好きに作ります。ここはいつもと全く同じ。上記のOn~にロジックを書くだけです。必要なら別メソッドや別クラスも自由に作ってください。

一通りプロパティやメソッドを用意しておけば、普段cBotを作ってるときとほぼ同じ感覚でコーディングできると思います。

動作確認がてらこんなコードを書いてみました。毎ティックスプレッドをログに出力するという特に意味のないcBotです。

    public void OnStart() {
        Print($"{SymbolName}のチャートで開始しました。");
    }
    public void OnTick() {
        Print($"スプレッド現在値{(Ask - Bid) / Symbol.PipSize:f1}pips");
    }
    public void OnBar() {
        Print($"{Time}:ローソク足が更新されました");
    }
    public void OnStop() {
        Print("停止しました");
    }

ここまでできたらCtrl+Shift+Bを押してビルドしてライブラリ側は完成です。

 

③本体(algoファイル)を作って呼び出す

algoファイルを新しく作成します。MyLogicMainとでもしておきましょうか。

作成したらVisualStudioで開いて、参照に今作ったライブラリを追加します。

上記ライブラリを作った場所を開いて、MyLogic\bin\debugの中にMyLogic.dllがあると思うのでそれを参照します。

今回はこれだけでも動くのですが、あとあとのことを考えるとターゲットフレームワークも変更してライブラリ側に合わせておく方がいいでしょう。(上記参照

あとは簡単、using MyLogicを冒頭で宣言して、本体側でMyTestLogicオブジェクト作って、各所でメソッド呼び出してあげるだけです。

using cAlgo.API;
using MyLogic;

namespace cAlgo.Robots {
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class MyLogicMain : Robot {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }

        MyTestLogic _logic;

        protected override void OnStart() {
            _logic = new MyTestLogic(this);
            _logic.OnStart();
        }

        protected override void OnTick() {
            _logic.OnTick();
        }

        protected override void OnBar() {
            _logic.OnBar();
        }

        protected override void OnStop() {
            _logic.OnStop();
        }
    }
}

上記の通り進めているのであれば、algoファイルの方はこれをコピペでいけるはずです。

基本こっちのファイルはパラメータを追加するときくらいしかいじることはありません。ここまでできたら閉じてしまっていいです。

注意点としては、ライブラリ側を変更してビルドしたら、本体(algoファイル)もビルドしないと変更が反映されません

面倒に感じるかもしれませんが、本体(algoファイル)側のビルドはcTrader内のボタン一つで済むため、大した手間ではありません。。

 

お試しあれ

最初だけ少し面倒ですが、簡単なcBotやインジケーターならともかく大掛かりなものを作るときはこの方法を使った方が結果的に効率は上がります

もしこの丸投げ型を頻繁に使うのであればライブラリ側のひな形をもう少し作り込んでおいた方がいいかもしれませんね。この辺はまた気が向いたら別で投稿します。

 


まだコメントはありません

新しいコメント

コメントは承認後に公開されます。承認まで次のコメントは投稿できません。

cTrader's Life

© 2025 ajinori