This is a bit complicated in Postgres. However, I question your logic. It would seem that a right outer join is not correct, because you are checking that the first table is not NULL. So this would seem to capture your logic:
UPDATE tr
SET (o_t, g_v, br, s_t, st, c_d, n_r, n_a, cd_id)
= (a.o_t, a.g_v, a.br, a.s_t, a.st, a.c_d, a.n_r, a.n_a,
a.cd_id)
FROM tr a JOIN
ht b
USING (date, name, ft );
The where clause is even redundant, because the value cannot be NULL due to the join condition. In any case, this doesn't work, but it does point to the right solution.
In Postgres, the table in the update cannot be in the FROM clause, unless your intention is a self join. So, try this version:
UPDATE tr
SET (o_t, g_v, br, s_t, st, c_d, n_r, n_a, cd_id)
= (a.o_t, a.g_v, a.br, a.s_t, a.st, a.c_d, a.n_r, a.n_a,
a.cd_id)
FROM tr a JOIN
ht b
USING (date, name, ft )
WHERE tr.date = a.date and tr.name = a.name and tr.ft = a.ft;
However, this update doesn't make sense. I suspect that you want the values to come from ht, NOT tr, when there is a match. If so, this is the simplest way:
UPDATE tr
SET (o_t, g_v, br, s_t, st, c_d, n_r, n_a, cd_id)
= (a.o_t, a.g_v, a.br, a.s_t, a.st, a.c_d, a.n_r, a.n_a,
a.cd_id)
FROM ht a
WHERE tr.date = a.date and tr.name = a.name and tr.ft = a.ft;
b?