Your sample queries always include both key_id and date, so it would be sensible to base an index on these columns. The main question is which column should be first and which second. This depends on the selectivity. The first column should be the one with the highest selectivity according to your query, so if you have more different days than different key_ids in your table, use the datetime column first, otherwise put the key_id in front.
If you have queries which only supply one of these columns in the WHERE clause, you could also resort to have an index for each of the columns, with the other as INCLUDED COLUMN.
Regarding the clustered index you have several options. Assuming the id column is an IDENTITY, you can use it for a clustered index. However that will lead to potentially expensive lookup operations with millions of records (i.e. a query over a month with most of the key_ids, where you also want to retrieve the value column(s)).
Another option would be to make one of the aforementioned indexes a clustered one. With the datetime in front (or as single key column) you will get almost no fragmentation, so the only drawback would be a slightly bigger size since its not unique, which forces SQL Server to add a 4-byte "uniqueifier" to each index entry. With the key_id in front you will get fragmentation which slows down both insert and range query performance (add padding and a reduced fillfactor in this case to reduce page splits and fragmentation).
Yet another option would be to partition the table in date ranges. With enterprise edition this would be built-in, but you can still do it manually with standard edition by creating multiple tables (say one for each month) and joining them with a view. The definition of the view has to be updated each time you add or remove another month table and this only makes sense performance-wise if you use date as a clustered index (maybe in combination with key_id) and add constraints to each table that restrict the date range to the respective month for the table. Then SQL Server can reliably exclude tables from the query which don't fall into the selected date range.
This last approach also gives you the opportunity to move older tables with unchanging data to read-only filegroups, greatly speeding up your backup process. Also getting rid of old data gets as easy as dropping a table (and modifying a view or two). But this only makes sense if the vast majority of your queries uses significant date restrictions.
Hope that helps.